Description
Input
Output
每次x=1时,每行一个整数,表示这次旅行的开心度
Sample Input
4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
Sample Output
101
11
11
11
11
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9
Solution
一个数最多只会被开根$loglog$次(因为每次开根相当于指数除$2$)。
然后用线段树维护一个区间和和区间最大值,如果这个区间的最大值小于等于$1$就没有做的必要了。
去年这个题写了个分块在$BZOJ$被卡了之后就扔着不管了……
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #define N (100009) 6 #define LL long long 7 using namespace std; 8 9 struct Sgt{LL max,sum;}Segt[N<<2]; 10 int n,m,a[N],opt,x,y; 11 12 inline int read() 13 { 14 int x=0,w=1; char c=getchar(); 15 while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();} 16 while (c>='0' && c<='9') x=x*10+c-'0', c=getchar(); 17 return x*w; 18 } 19 20 void Build(int now,int l,int r) 21 { 22 if (l==r) {Segt[now].max=a[l]; Segt[now].sum=a[l]; return;} 23 int mid=(l+r)>>1; 24 Build(now<<1,l,mid); Build(now<<1|1,mid+1,r); 25 Segt[now].sum=Segt[now<<1].sum+Segt[now<<1|1].sum; 26 Segt[now].max=max(Segt[now<<1].max,Segt[now<<1|1].max); 27 } 28 29 void Update(int now,int l,int r,int l1,int r1) 30 { 31 if (Segt[now].max<=1 || l>r1 || r<l1) return; 32 if (l==r) {Segt[now].max=Segt[now].sum=sqrt(Segt[now].sum); return;} 33 int mid=(l+r)>>1; 34 Update(now<<1,l,mid,l1,r1); Update(now<<1|1,mid+1,r,l1,r1); 35 Segt[now].sum=Segt[now<<1].sum+Segt[now<<1|1].sum; 36 Segt[now].max=max(Segt[now<<1].max,Segt[now<<1|1].max); 37 } 38 39 LL Query(int now,int l,int r,int l1,int r1) 40 { 41 if (l>r1 || r<l1) return 0; 42 if (l1<=l && r<=r1) return Segt[now].sum; 43 int mid=(l+r)>>1; 44 return Query(now<<1,l,mid,l1,r1)+Query(now<<1|1,mid+1,r,l1,r1); 45 } 46 47 int main() 48 { 49 n=read(); 50 for (int i=1; i<=n; ++i) a[i]=read(); 51 Build(1,1,n); 52 m=read(); 53 while (m--) 54 { 55 opt=read(); x=read(); y=read(); 56 if (opt==1) printf("%lld ",Query(1,1,n,x,y)); 57 else Update(1,1,n,x,y); 58 } 59 }