您的位置:首页 > 其它

hdu 4578 Transformation(线段树区间操作)

2017-03-13 14:44 323 查看

题目链接:hdu 4578 Transformation

题意:

有n个数一开始全为0,现在有m个操作.

1 a b c :将[a,b]区间的数全部加c

2 a b c :将[a,b]区间的数全部乘c

3 a b c :将[a,b]区间的数全部set成c

4 a b p :询问[a,b]区间的数的p次方的和

题解:

2,3操作都方便操作,1要推一下公式。

(a + c)2 = a2 + c2 + 2ac  , 即sum2[rt] = sum2[rt] + (r - l + 1) * c * c + 2 * sum1[rt] * c;

(a + c)3 = a3 + c3 + 3a(a2 + ac) , 即sum3[rt] = sum3[rt] + (r - l + 1) * c * c * c + 3 * c * (sum2[rt] + sum1[rt] * c);

然后要注意的坑点:

mul的时候add也要成上c,set的时候mul要变为1,add变为0。

然后pushdown的时候先更新set,然后更新mul,然后add。

1 #include<bits/stdc++.h>
2 #define ls l,m,rt<<1
3 #define rs m+1,r,rt<<1|1
4 #define mst(a,b) memset(a,b,sizeof(a))
5 #define F(i,a,b) for(int i=a;i<=b;++i)
6 using namespace std;
7
8 const int N=1e5+7,P=10007;
9
10 int add[N*4],mul[N*4],chang[N*4],sum[N*4][4];
11
12 int n,m;
13
14 void del(int a,int num,int d,int rt)
15 {
16     if(a==1)
17     {
18         add[rt]=(add[rt]+d)%P;
19         sum[rt][3]=(sum[rt][3]+d*d%P*d%P*num%P+3*d*sum[rt][2]%P+3*d*d%P*sum[rt][1]%P)%P;
20         sum[rt][2]=(sum[rt][2]+d*d%P*num%P+2*d*sum[rt][1]%P)%P;
21         sum[rt][1]=(sum[rt][1]+num*d)%P;
22     }
23     else if(a==2)
24     {
25         add[rt]=add[rt]*d%P;
26         mul[rt]=(mul[rt]*d)%P;
27         sum[rt][1]=sum[rt][1]*d%P;
28         sum[rt][2]=sum[rt][2]*d%P*d%P;
29         sum[rt][3]=sum[rt][3]*d%P*d%P*d%P;
30     }
31     else
32     {
33         add[rt]=0;
34         mul[rt]=1;
35         chang[rt]=d%P;
36         sum[rt][1]=d*num%P;
37         sum[rt][2]=d*d%P*num%P;
38         sum[rt][3]=d*d%P*d%P*num%P;
39     }
40 }
41
42 void pd(int rt,int l,int r)
43 {
44     int m=l+r>>1;
45     if(chang[rt])
46     {
47         del(3,m-l+1,chang[rt],rt<<1);
48         del(3,r-m,chang[rt],rt<<1|1);
49         chang[rt]=0;
50     }
51     if(mul[rt]!=1)
52     {
53         del(2,m-l+1,mul[rt],rt<<1);
54         del(2,r-m,mul[rt],rt<<1|1);
55         mul[rt]=1;
56     }
57     if(add[rt])
58     {
59         del(1,m-l+1,add[rt],rt<<1);
60         del(1,r-m,add[rt],rt<<1|1);
61         add[rt]=0;
62     }
63 }
64
65 void up(int rt)
66 {
67     F(i,1,3)sum[rt][i]=(sum[rt<<1][i]+sum[rt<<1|1][i])%P;
68 }
69
70 void update(int a,int b,int c,int d,int l=1,int r=n,int rt=1)
71 {
72     if(b<=l&&r<=c)
73     {
74         del(a,r-l+1,d,rt);
75         return;
76     }
77     pd(rt,l,r);
78     int m=l+r>>1;
79     if(b<=m)update(a,b,c,d,ls);
80     if(c>m)update(a,b,c,d,rs);
81     up(rt);
82 }
83
84 int ask(int L,int R,int p,int l=1,int r=n,int rt=1)
85 {
86     if(L<=l&&r<=R)return sum[rt]

; 87 pd(rt,l,r); 88 int m=l+r>>1,ans=0; 89 if(L<=m)ans=(ans+ask(L,R,p,ls))%P; 90 if(R>m)ans=(ans+ask(L,R,p,rs))%P; 91 up(rt); 92 return ans; 93 } 94 95 int main() 96 { 97 while(scanf("%d%d",&n,&m),n+m) 98 { 99 mst(add,0),mst(mul,0),mst(chang,0),mst(sum,0); 100 int a,b,c,d; 101 F(i,1,m) 102 { 103 scanf("%d%d%d%d",&a,&b,&c,&d); 104 if(a!=4)update(a,b,c,d); 105 else printf("%d\n",ask(b,c,d)); 106 } 107 } 108 return 0; 109 }

View Code [p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: