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