Description
维护序列,支持区间开方下取整,区间求和。
Solution
对线段树上的每个 Node 记录最大值 \(mx\)
修改操作时,若当前结点 \(mx=1\) 则不用继续修改
(代码里有很多冗余的东西请手动忽略)
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define lc p*2,l,(l+r)/2
#define rc p*2+1,(l+r)/2+1,r
#define NULLNODE {-1e18,1e18,0}
const int N = 400005;
int n,m,a[N],t1,t2,t3;
struct Node
{
int mx,mn,sum;
Node operator + (const Node &b) const
{
Node res;
res.mn=min(mn,b.mn);
res.mx=max(mx,b.mx);
res.sum=sum+b.sum;
return res;
}
bool ok()
{
return mx==1 || sum==mx;
}
void set(int x,int len)
{
mx=mn=x;
sum=len*x;
}
};
Node node[N];
void build(int p,int l,int r)
{
if(l==r)
{
node[p].set(a[l],1);
}
else
{
build(lc);
build(rc);
node[p]=node[p*2]+node[p*2+1];
}
}
void modify(int p,int l,int r,int ql,int qr)
{
if(l>qr||r<ql) return;
if(l>=ql&&r<=qr&&node[p].ok())
{
node[p].set(sqrt(node[p].mx+0.1),r-l+1);
}
else
{
modify(lc,ql,qr);
modify(rc,ql,qr);
node[p]=node[p*2]+node[p*2+1];
}
}
Node query(int p,int l,int r,int ql,int qr)
{
if(l>qr||r<ql) return NULLNODE;
if(l>=ql&&r<=qr) return node[p];
return query(lc,ql,qr)+query(rc,ql,qr);
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>t1>>t2>>t3;
if(t2>t3) swap(t2,t3);
if(t1==0)
{
modify(1,1,n,t2,t3);
}
else
{
cout<<query(1,1,n,t2,t3).sum<<endl;
}
}
}