BZOJ 3211 花神游历各国 线段树
BZOJ 3211 花神游历各国 线段树
各数根号之和无法合并,无法用线段树维护,只能暴力开根号(毒瘤)。但是又注意到\(10^9\)级别的数开方次数不超过10,任何数(除\(0\))开到最后都为\(1\),并且后续修改操作并不会再修改值,所以维护区间和,区间正常查询,区间递归到每一个数暴力修改,修改后检查并标记一下无法再被修改的区间,下一次修改时直接跳过。
注意:后续修改对\(0\)也无效,所以\(0\)和\(1\)到要标记(否则\(T\)到50)
#include <cstdio>
#include <cmath>
#define ll long long
#define sl (x<<1)
#define sr (x<<1|1)
#define MAXN 100010
using namespace std;
struct nod{
int l; int r;
ll lazy; ll val;
bool over;
} tre[MAXN*4];
int a[MAXN];
int s[MAXN][10];
int n;
void buildt(int l, int r, int x){
tre[x].l=l;
tre[x].r=r;
tre[x].over=0;
if(l==r){
tre[x].val=a[l];
return;
}
int mid=(l+r)>>1;
buildt(l, mid, sl);
buildt(mid+1, r, sr);
tre[x].val=tre[sl].val+tre[sr].val;
tre[x].over=tre[sl].over&&tre[sr].over;
}
void change(int x, int cl, int cr){
if(tre[x].over) return;
if(tre[x].l==tre[x].r){
tre[x].val=sqrt(tre[x].val);
if(tre[x].val==1||tre[x].val==0) tre[x].over=1;
return;
}
int mid=(tre[x].l+tre[x].r)>>1;
if(cl<=mid) change(sl, cl, cr);
if(cr>mid) change(sr, cl, cr);
tre[x].val=tre[sl].val+tre[sr].val;
tre[x].over=tre[sl].over&&tre[sr].over;
}
ll query(int x, int ql, int qr){
if(ql<=tre[x].l&&tre[x].r<=qr){
return tre[x].val;
}
int mid=(tre[x].l+tre[x].r)>>1;
ll ans=0;
if(ql<=mid) ans+=query(sl, ql, qr);
if(qr>mid) ans+=query(sr, ql, qr);
return ans;
}
int main()
{
scanf("%d", &n);
for(int i=1;i<=n;++i)
scanf("%d", &a[i]);
buildt(1,n,1);
int m;
scanf("%d", &m);
while(m--){
int x,l,r;
scanf("%d %d %d", &x, &l, &r);
if(x==1) printf("%lld\n", query(1,l,r));
else change(1, l, r);
}
return 0;
}