【HDU4578 Transformation】线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578

 

题意:有一个序列,有四种操作:

1:区间[l,r]内的数全部加c。

2:区间[l,r]内的数全部乘c。

3:区间[l,r]内的数全部初始为c。

4:询问区间[l,r]内所有数的P次方之和。

思路:比较复杂的线段树操作。只有一个询问操作,那就是询问[l,r]之间数的p次方之和,我们不可能全部查询的节点,会TLE,最好的情况就是查询到一段[a,b],这段区间内所有的值都相等,那么返回(b-a+1)*val 的值即可。 根据询问操作我们即可意识到我们要维护的是区间内所有值都相同的情况的区间。对于覆盖和加乘操作,我开始以为向下传递两层即可,这样是错误的,因为即可传递下去两层,还是有可能同时存在加乘操作。所以我们可以分两种情况讨论:1、当为覆盖操作时,直接覆盖区间即可,并且把标记的加乘操作赋为初始值。2、当为加乘操作时,先判断当前区间段是否为相同的值,是的话直接加乘,维护这个相同的值即可。如果不相同,看区间是否已有加乘标记,把这个加乘标记一直传递下去,知道遇见那个区间段区间所有值的相同停止。最后把这个加乘赋给最开始的区间段。简单的说就是,覆盖操作可直接维护,不是覆盖操作的话,区间只能保留一个加乘操作。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 
  7 #define lz 2*u,l,mid
  8 #define rz 2*u+1,mid+1,r
  9 typedef long long lld;
 10 const int maxn=100005;
 11 const int mod=10007;
 12 lld add[4*maxn], mul[4*maxn], ch[4*maxn], sum[4*maxn];
 13 
 14 void build(int u, int l, int r)
 15 {
 16     mul[u]=1;
 17     add[u]=sum[u]=0;
 18     ch[u]=0;
 19     if(l==r)
 20     {
 21         ch[u]=1;
 22         return ;
 23     }
 24     int mid=(l+r)>>1;
 25     build(lz);
 26     build(rz);
 27 }
 28 
 29 void push_down(int u, int l, int r)
 30 {
 31     if(l==r) return ;
 32     int mid=(l+r)>>1;
 33     if(ch[u])
 34     {
 35         add[2*u]=0, mul[2*u]=1;
 36         add[2*u+1]=0, mul[2*u+1]=1;
 37         ch[2*u]=ch[2*u+1]=1;
 38         sum[2*u]=sum[2*u+1]=sum[u];
 39         ch[u]=0;
 40     }
 41     else
 42     {
 43         if(add[u])
 44         {
 45             if(ch[2*u]) sum[2*u]=(sum[2*u]+add[u])%mod;
 46             else
 47             {
 48                 push_down(lz);
 49                 add[2*u]=(add[2*u]+add[u])%mod;
 50             }
 51             if(ch[2*u+1]) sum[2*u+1]=(sum[2*u+1]+add[u])%mod;
 52             else
 53             {
 54                 push_down(rz);
 55                 add[2*u+1]=(add[2*u+1]+add[u])%mod;
 56             }
 57             add[u]=0;
 58         }
 59         if(mul[u]>1)
 60         {
 61             if(ch[2*u]) sum[2*u]=(sum[2*u]*mul[u])%mod;
 62             else
 63             {
 64                 push_down(lz);
 65                 mul[2*u]=(mul[2*u]*mul[u])%mod;
 66             }
 67             if(ch[2*u+1]) sum[2*u+1]=(sum[2*u+1]*mul[u])%mod;
 68             else
 69             {
 70                 push_down(rz);
 71                 mul[2*u+1]=(mul[2*u+1]*mul[u])%mod;
 72             }
 73             mul[u]=1;
 74         }
 75     }
 76 }
 77 
 78 void Update(int u, int l, int r, int tl, int tr, int c, int op)
 79 {
 80     if(tl<=l&&r<=tr)
 81     {
 82         if(op==3)
 83         {
 84             ch[u]=1;
 85             mul[u]=1, add[u]=0;
 86             sum[u]=c;
 87         }
 88         else
 89         {
 90             if(ch[u])
 91             {
 92                 if(op==1) sum[u]=(sum[u]+c)%mod;
 93                 else   sum[u]=sum[u]*c%mod;
 94             }
 95             else
 96             {
 97                 push_down(u,l,r);
 98                 if(op==1) add[u]=(add[u]+c)%mod;
 99                 else mul[u]=mul[u]*c%mod;
100             }
101         }
102         return ;
103     }
104     push_down(u,l,r);
105     int mid=(l+r)>>1;
106     if(tr<=mid) Update(lz,tl,tr,c,op);
107     else if(tl>mid) Update(rz,tl,tr,c,op);
108     else
109     {
110         Update(lz,tl,mid,c,op);
111         Update(rz,mid+1,tr,c,op);
112     }
113 }
114 
115 lld Query(int u, int l, int r, int tl, int tr, int p)
116 {
117     if(tl<=l&&r<=tr)
118     {
119         if(ch[u])
120         {
121             lld ans=1, tp=sum[u];
122             for(int i=1; i<=p; i++) ans=ans*tp%mod;
123             return (r-l+1)*ans%mod;
124         }
125     }
126     push_down(u,l,r);
127     int mid=(l+r)>>1;
128     if(tr<=mid) return Query(lz,tl,tr,p);
129     else if(tl>mid) return Query(rz,tl,tr,p);
130     else
131     {
132         lld t1=Query(lz,tl,mid,p);
133         lld t2=Query(rz,mid+1,tr,p);
134         return (t1+t2)%mod;
135     }
136 }
137 
138 int main()
139 {
140     int n, m;
141     while(cin >> n >> m, n+m)
142     {
143         build(1,1,n);
144         for(int i=1; i<=m; i++)
145         {
146             int l, r, c, op;
147             scanf("%d%d%d%d",&op,&l,&r,&c);
148             if(op<=3) Update(1,1,n,l,r,c,op);
149             else printf("%I64d\n",Query(1,1,n,l,r,c)%mod);
150         }
151     }
152     return 0;
153 }
View Code

 

posted @ 2013-08-14 11:25  Mr. Ant  阅读(1307)  评论(0编辑  收藏  举报