• 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 }

     

  • 相关阅读:
    《MySQL必知必会》第二十三章:使用存储过程
    《MySQL必知必会》第二十四章:使用游标
    《MySQL必知必会》第二十五章:使用触发器
    《MySQL必知必会》第二十章:更新和删除数据
    《MySQL必知必会》第二十一章:创建和操纵表
    《MySQL必知必会》第二十二章:使用视图
    《MySQL必知必会》第十七章:组合查询
    《MySQL必知必会》第十八章:全文本搜索
    [LeetCode] 930. Binary Subarrays With Sum
    [LeetCode] 676. Implement Magic Dictionary
  • 原文地址:https://www.cnblogs.com/-maybe/p/4815002.html
Copyright © 2020-2023  润新知