POJ 4047 Garden 线段树 区间更新

给出一个n个元素的序列,序列有正数也有负数

支持3个操作:

p x y

0.p=0时,把第x个的值改为y

1.p=1时,交换第x个和第y个的值

2.p=2时,问区间[x,y]里面连续k个的子序列的最大和(保证y-x+1>=k)

我们只要定义数组v

v[i]表示原序列中,从第i个开始,连续k个元素的值的和

然后我们只需要维护一棵线段树,树的叶子节点表示数组v

树的节点维护:

区间[l,r]中,连续k个的子序列的最大和,即数组v的最大值

这样的话,3个操作就变为:

0.把区间[max(x-k+1,0),x]的值加y-init_v[x]

1.区间[max(x-k+1,0),x]加上init_v[y]-init_v[x]

 区间[max(y-k+1,0),y]加上init_v[x]-init_v[y]

 交换init_v[x]和init_v[y]的值

2.求max[x,y-k+1]

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 
  5 using namespace std;
  6 
  7 #define ll long long
  8 #define lson l,m,rt<<1
  9 #define rson m+1,r,rt<<1|1
 10 
 11 const int maxn=200000+5;
 12 const int inf=0x3f3f3f3f;
 13 
 14 int init_v[maxn];
 15 int init_sum[maxn];
 16 int v[maxn<<2];
 17 int lazy[maxn<<2];
 18 int n,m,k;
 19 
 20 void solve();
 21 
 22 int main()
 23 {
 24     int test;
 25     scanf("%d",&test);
 26     while(test--){
 27         scanf("%d %d %d",&n,&m,&k);
 28         for(int i=1;i<=n;i++){
 29             scanf("%d",&init_v[i]);
 30         }
 31         solve();
 32     }
 33     return 0;
 34 }
 35 
 36 void pushup(int rt)
 37 {
 38     v[rt]=max(v[rt<<1],v[rt<<1|1]);
 39 }
 40 
 41 void pushdown(int rt)
 42 {
 43     if(lazy[rt]){
 44         lazy[rt<<1]+=lazy[rt];
 45         lazy[rt<<1|1]+=lazy[rt];
 46         v[rt<<1]+=lazy[rt];
 47         v[rt<<1|1]+=lazy[rt];
 48         lazy[rt]=0;
 49     }
 50 }
 51 
 52 void build(int l,int r,int rt)
 53 {
 54     if(l==r){
 55         v[rt]=init_sum[l+k-1]-init_sum[l-1];
 56         return ;
 57     }
 58     int m=(l+r)>>1;
 59     build(lson);
 60     build(rson);
 61     pushup(rt);
 62 }
 63 
 64 void update(int L,int R,int add,int l,int r,int rt)
 65 {
 66     if(L<=l&&R>=r){
 67         lazy[rt]+=add;
 68         v[rt]+=add;
 69         return ;
 70     }
 71     int m=(l+r)>>1;
 72     pushdown(rt);
 73     if(L<=m)
 74         update(L,R,add,lson);
 75     if(R>m)
 76         update(L,R,add,rson);
 77     pushup(rt);
 78 }
 79 
 80 int query(int L,int R,int l,int r,int rt)
 81 {
 82     if(L<=l&&R>=r){
 83         return v[rt];
 84     }
 85     int m=(l+r)>>1;
 86     pushdown(rt);
 87     int ret=-inf;
 88     if(L<=m)
 89         ret=max(ret,query(L,R,lson));
 90     if(R>m)
 91         ret=max(ret,query(L,R,rson));
 92 
 93     return ret;
 94 }
 95 
 96 void solve()
 97 {
 98     init_sum[0]=0;
 99     for(int i=1;i<=n;i++){
100         init_sum[i]=init_sum[i-1]+init_v[i];
101     }
102 
103     build(1,n,1);
104     memset(lazy,0,sizeof lazy);
105     for(int i=1;i<=m;i++){
106         int p,x,y;
107         scanf("%d %d %d",&p,&x,&y);
108         if(p==0){
109             update(max(x-k+1,0),x,y-init_v[x],1,n,1);
110             init_v[x]=y;
111         }
112         else if(p==1){
113             update(max(x-k+1,0),x,init_v[y]-init_v[x],1,n,1);
114             update(max(y-k+1,0),y,init_v[x]-init_v[y],1,n,1);
115             swap(init_v[x],init_v[y]);
116         }
117         else{
118             printf("%d
",query(x,y-k+1,1,n,1));
119         }
120     }
121     return ;
122 }

 

原文地址:https://www.cnblogs.com/-maybe/p/4815002.html