1. 程式人生 > >"盛大遊戲杯" M 風力觀測 (線段樹)

"盛大遊戲杯" M 風力觀測 (線段樹)

bit int fin 題目 val space dac 最大的 bits

題目鏈接:"盛大遊戲杯" M 風力觀測

題意:

給你n個數,現在有m個操作。

1 L R V 給[L,R]區間全部加V.

2 X 詢問X這個點 歷史的絕對值最大是多少。

題解:

對於每個詢問,其實我們只需要記錄下在這個過程中最大的偏移量和最小的偏移量就行了。

所以直接一個線段樹搞一搞就行了。

技術分享
 1 #include<bits/stdc++.h>
 2 #define ls l,m,rt<<1
 3 #define rs m+1,r,rt<<1|1
 4 #define mst(a,b) memset(a,b,sizeof(a))
 5 #define F(i,a,b) for(int i=a;i<=b;++i)
 6
using namespace std; 7 8 const int N=1e5+7; 9 int mx[N*4],mi[N*4],val[N*4]; 10 int n,a[N],t,m; 11 12 void PD(int rt) 13 { 14 if(mx[rt]||mi[rt]) 15 { 16 int tmp=val[rt<<1]+mx[rt]; 17 if(tmp>0)mx[rt<<1]=max(mx[rt<<1],tmp); 18 tmp=val[rt<<1
]+mi[rt]; 19 if(tmp<0)mi[rt<<1]=min(mi[rt<<1],val[rt<<1]+mi[rt]); 20 tmp=val[rt<<1|1]+mx[rt]; 21 if(tmp>0)mx[rt<<1|1]=max(mx[rt<<1|1],tmp); 22 tmp=val[rt<<1|1]+mi[rt]; 23 if(tmp<0)mi[rt<<1|1]=min(mi[rt<<1
|1],tmp); 24 val[rt<<1]+=val[rt],val[rt<<1|1]+=val[rt]; 25 mx[rt]=mi[rt]=val[rt]=0; 26 } 27 } 28 29 void update(int L,int R,int v,int l=1,int r=n,int rt=1) 30 { 31 if(L<=l&&r<=R) 32 { 33 val[rt]+=v; 34 if(val[rt]>0)mx[rt]=max(mx[rt],val[rt]); 35 else mi[rt]=min(mi[rt],val[rt]); 36 return; 37 } 38 PD(rt); 39 int m=l+r>>1; 40 if(L<=m)update(L,R,v,ls); 41 if(R>m)update(L,R,v,rs); 42 } 43 44 void query(int &mmx,int &mmi,int x,int l=1,int r=n,int rt=1) 45 { 46 if(l==r){mmx=mx[rt],mmi=mi[rt];return;} 47 PD(rt); 48 int m=l+r>>1; 49 if(x<=m)query(mmx,mmi,x,ls); 50 else query(mmx,mmi,x,rs); 51 } 52 53 int main(){ 54 scanf("%d",&t); 55 while(t--) 56 { 57 scanf("%d%d",&n,&m); 58 mst(mx,0),mst(mi,0),mst(val,0); 59 F(i,1,n)scanf("%d",a+i); 60 F(i,1,m) 61 { 62 int x,l,r,v; 63 scanf("%d",&x); 64 if(x==1) 65 { 66 scanf("%d%d%d",&l,&r,&v); 67 update(l,r,v); 68 } 69 else 70 { 71 scanf("%d",&x); 72 int mmx,mmi; 73 query(mmx,mmi,x); 74 printf("%d\n",max(abs(mmx+a[x]),abs(mmi+a[x]))); 75 } 76 } 77 } 78 return 0; 79 }
View Code

"盛大遊戲杯" M 風力觀測 (線段樹)