zoukankan      html  css  js  c++  java
  • 对于在线段树上修改整段区间的理解

    第一题

    HDU1698http://acm.hdu.edu.cn/showproblem.php?pid=1698

    这是在区间上进行整段的修改操作,我们就用to[]数组代表修改的lazy标记

    记住在构建树和在change函数中自顶向下更新的时候,一定要注意重新回去更新上层的节点,所以末尾需加上update(cur)

     1 #include <cstdio>
     2 #include <cstring>
     3 using namespace std;
     4 #define N 100005
     5 int sum[4*N],to[4*N];
     6 
     7 void update(int x)
     8 {
     9     sum[x]=sum[x<<1]+sum[x<<1|1];
    10 }
    11 void build(int cur,int x,int y)
    12 {
    13     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    14     to[cur]=0;
    15     if(x==y){
    16         sum[cur]=1;
    17         return;
    18     }
    19     build(ls,x,mid);
    20     build(rs,mid+1,y);
    21     update(cur);
    22 }
    23 void pushdown(int cur,int x,int y)
    24 {
    25     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    26     if(to[cur]!=0){
    27         to[ls]=to[rs]=to[cur];
    28         sum[ls]=(mid-x+1)*to[cur];
    29         sum[rs]=(y-mid)*to[cur];
    30         to[cur]=0;
    31     }
    32 }
    33 void change(int cur,int x,int y,int s,int t,int v)
    34 {
    35     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    36     if(x>=s&&y<=t){
    37         sum[cur]=(y-x+1)*v;
    38         to[cur]=v;
    39         return;
    40     }
    41     pushdown(cur,x,y);
    42     if(mid>=s) change(ls,x,mid,s,t,v);
    43     if(mid+1<=t) change(rs,mid+1,y,s,t,v);
    44     update(cur);
    45 }
    46 void query(int cur,int x,int y,int s,int t,int &ans)
    47 {
    48     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    49     if(x>=s&&y<=t){
    50         ans+=sum[cur];
    51         return;
    52     }
    53     pushdown(cur,x,y);
    54     if(mid>=s) query(ls,x,mid,s,t,ans);
    55     if(mid+1<=t) query(rs,mid+1,y,s,t,ans);
    56 }
    57 int main()
    58 {
    59     int T,n,Q,a,b,c,ans;
    60     scanf("%d",&T);
    61     for(int i=1;i<=T;i++){
    62         ans=0;
    63         scanf("%d%d",&n,&Q);
    64         build(1,1,n);
    65         for(int j=0;j<Q;j++){
    66             scanf("%d%d%d",&a,&b,&c);
    67             change(1,1,n,a,b,c);
    68         }
    69         query(1,1,n,1,n,ans);
    70         printf("Case %d: The total value of the hook is %d.
    ",i,ans);
    71     }
    72     return 0;
    73 }
    View Code

    第二题
    POJ3468http://poj.org/problem?id=3468

    这是在一段区间上添加值,所以与上题的操作不一样,对于每个相加的数,我们应该也不断将lazy节点累加,类似这种的累加操作,我们总是选择

    用add[]数组作为lazy标记

    当然这道题特别坑的是因为在累加过程中可以达到10000*100000这样子就超过了int的类型,我们就要用LL来定义sum[],add[]和ans

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 #define N 100005
     6 #define LL long long
     7 int a[N];
     8 LL sum[4*N],add[4*N];
     9 void update(int x)
    10 {
    11     sum[x]=sum[x<<1]+sum[x<<1|1];
    12 }
    13 void build(int cur,int x,int y)
    14 {
    15     add[cur]=0;
    16     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    17     if(x==y){
    18         sum[cur]=a[x];
    19         return;
    20     }
    21     build(ls,x,mid);
    22     build(rs,mid+1,y);
    23     update(cur);
    24 }
    25 void pushdown(int cur,int x,int y)
    26 {
    27     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    28     if(add[cur]!=0){
    29         add[ls]+=add[cur];
    30         add[rs]+=add[cur];
    31         sum[ls]+=(mid-x+1)*add[cur];
    32         sum[rs]+=(y-mid)*add[cur];
    33         add[cur]=0;
    34     }
    35 }
    36 void change(int cur,int x,int y,int s,int t,int v)
    37 {
    38     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    39     if(x>=s&&y<=t){
    40         sum[cur]+=(y-x+1)*v;
    41         add[cur]+=v;
    42         return;
    43     }
    44     pushdown(cur,x,y);
    45     if(mid>=s) change(ls,x,mid,s,t,v);
    46     if(mid<t) change(rs,mid+1,y,s,t,v);
    47     update(cur);
    48 }
    49 void query(int cur,int x,int y,int s,int t,LL &ans)
    50 {
    51     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    52     if(x>=s&&y<=t){
    53         ans+=sum[cur];
    54         return;
    55     }
    56     pushdown(cur,x,y);
    57     if(mid>=s) query(ls,x,mid,s,t,ans);
    58     if(mid<t) query(rs,mid+1,y,s,t,ans);
    59 }
    60 int main()
    61 {
    62     int q,n,x,y,z;
    63     char c;
    64     while(scanf("%d%d",&n,&q)!=EOF){
    65         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    66         build(1,1,n);
    67         for(int i=1;i<=q;i++){
    68             cin>>c;
    69             if(c=='C'){
    70                 scanf("%d%d%d",&x,&y,&z);
    71                 change(1,1,n,x,y,z);
    72             }
    73             else{
    74                 scanf("%d%d",&x,&y);
    75                 LL ans=0;
    76                 query(1,1,n,x,y,ans);
    77                 printf("%I64d
    ",ans);
    78             }
    79         }
    80     }
    81     return 0;
    82 }
    View Code

     第三题

    这是对于是否整除3的数的个数求和,这里用add[]不断累加lazy标记,但是要分情况讨论余1,余2两种情况

    SPOJ MULTQ3 这道题目特别容易超时。。。我就不吐槽我自己一会提交成功一会TLE了,感觉要看运气~~

    这道题目主要考虑在pushdown上面的修改,因为是否为3的整数倍,中间有余1和余2两种情况要进行考虑

    另外我们增添两个数组来保存余1和余2的个数,当然你也可以考虑用2维数组,这里情况比较少,多建几个数组也不是很麻烦

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define N 100005
    int sum1[4*N],sum2[4*N],sum3[4*N],a[N],add[4*N];
    
    void update(int cur)
    {
        sum1[cur]=sum1[cur<<1]+sum1[cur<<1|1];
        sum2[cur]=sum2[cur<<1]+sum2[cur<<1|1];
        sum3[cur]=sum3[cur<<1]+sum3[cur<<1|1];
    }
    void build(int cur,int x,int y)
    {
        add[cur]=0;
        int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
        if(x==y){
            sum1[cur]=1;
            sum2[cur]=0;
            sum3[cur]=0;
            return;
        }
        build(ls,x,mid);
        build(rs,mid+1,y);
        update(cur);
    }
    
    void pushdown(int cur,int x,int y)
    {
        int ls=cur<<1,rs=cur<<1|1;
        if(add[cur]%3!=0)
        {
            add[ls]+=add[cur],add[rs]+=add[cur];
            if(add[cur]%3==1){
                int temp=sum1[ls];
                sum1[ls]=sum3[ls];
                sum3[ls]=sum2[ls];
                sum2[ls]=temp;
                temp=sum1[rs];
                sum1[rs]=sum3[rs];
                sum3[rs]=sum2[rs];
                sum2[rs]=temp;
            }
            else if(add[cur]%3==2){
                int temp=sum2[ls];
                sum2[ls]=sum3[ls];
                sum3[ls]=sum1[ls];
                sum1[ls]=temp;
                temp=sum2[rs];
                sum2[rs]=sum3[rs];
                sum3[rs]=sum1[rs];
                sum1[rs]=temp;
            }
            add[cur]=0;
        }
    }
    
    void change(int cur,int x,int y,int s,int t,int v)
    {
        int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
        if(x>=s&&y<=t){
            int temp;
            temp=sum1[cur];
            sum1[cur]=sum3[cur];
            sum3[cur]=sum2[cur];
            sum2[cur]=temp;
            add[cur]+=v;
            return;
        }
        pushdown(cur,x,y);
        if(mid>=s) change(ls,x,mid,s,t,v);
        if(mid+1<=t) change(rs,mid+1,y,s,t,v);
        update(cur);
    }
    void query(int cur,int x,int y,int s,int t,int &ans)
    {
        int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
        if(x>=s&&y<=t){
            ans+=sum1[cur];
            return;
        }
        pushdown(cur,x,y);
        if(mid>=s) query(ls,x,mid,s,t,ans);
        if(mid+1<=t) query(rs,mid+1,y,s,t,ans);
    }
    int main()
    {
        int n,q,log,a,b;
        while(scanf("%d%d",&n,&q)!=EOF){
            build(1,0,n-1);
            for(int i=0;i<q;i++){
                scanf("%d",&log);
                if(log==0){
                    scanf("%d%d",&a,&b);
                    change(1,0,n-1,a,b,1);
                }
                else{
                    scanf("%d%d",&a,&b);
                    int ans=0;
                    query(1,0,n-1,a,b,ans);
                    printf("%d
    ",ans);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    sqlserver 库服务器导数据
    C# 关于X86/X64/AnyCpu 的关系
    VisualStudio相关序列号
    超级搜索术
    ffmypeg 视频处理类库使用方法
    远程桌面连接
    关于VS2013调试IIS应用源代码时无法进入断点的问题总结
    C#访问修饰符(public,private,protected,internal,sealed,abstract)
    MySQL结构相关
    性能瓶颈定位分析
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/3886044.html
Copyright © 2011-2022 走看看