1. 程式人生 > >BZOJ3211:花神遊歷各國(線段樹)

BZOJ3211:花神遊歷各國(線段樹)

col 開心 return 如果 mes pac () inline else

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

Sample Output

101
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\n",Query(1,1,n,x,y)); 57 else Update(1,1,n,x,y); 58 } 59 }

BZOJ3211:花神遊歷各國(線段樹)