第一题

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.\n",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\n",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\n",ans);
            }
        }
    }
    return 0;
}
View Code

 

 posted on 2014-08-02 00:08  Love风吟  阅读(651)  评论(0编辑  收藏  举报