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

题目链接: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][p];
 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

 

转载于:https://www.cnblogs.com/bin-gege/p/6542766.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值