HDU4578——Transformation(线段树)

来源:互联网 发布:javascript 数组对象 编辑:程序博客网 时间:2024/04/30 05:15

又是一道很裸的线段树,一个数列a1, a2, …, an,然后4种操作:

1,x,y,c:将ax到ay之间的数都加c

2,x,y,c:将ax到ay之间的数都乘以c

3,x,y,c:将ax到ay之间的数变成c

4,x,y,p:求出ax到ay之间数字的p次幂的和,p=1,2,3,结果对10007取模

首先肯定要先保存3个次幂的和,然后对于每个结点用a和b作标记,f表示需要pushdown,则每个数i可以表示成ai+b

把上面三个操作做个统一,就是输入给一组(j,k),计算j(ai+b)+k=j*ai + j*b+k,并将系数重新赋值给a和b

三种操作的参数如下:

1:(1,c)

2:(c,0)

3:(0,c)

然后是传入(j,k)三个和的变化,这个公式也不难推导,但要注意计算的顺序应该是从高次往低次更新,因为高次的计算总要利用到低次的结果

每次pushdown后a=1,b=0,f=0

剩下就只是实现上的细节了

PS:因为各种脑残手抽WA了几次才A,以后还是要注意细节方面的问题

//HDU 4578 3671MS 9952K 2560B G++//Author: hongrock#include<cstdio>#include<cstring>#define LEFT(a) ((a)<<1)#define RIGHT(a) (((a)<<1)|1)#define MID(a,b) (((a)+(b))>>1) #define MAXN 400010#define MOD 10007int n, q, op, x, y, c, s, l[MAXN], r[MAXN], a[MAXN], b[MAXN], sum[MAXN][3];bool f[MAXN];char ch;int getnum(){s=0;ch=getchar();while(ch<48 || ch>57)ch=getchar();while(ch>=48 && ch<=57){s = s*10+ch-48;ch = getchar();}return s;}void build(int o, int ll, int rr){l[o]=ll;r[o]=rr;a[o]=1;if(ll<rr){int m = MID(ll,rr);build(LEFT(o), ll, m);build(RIGHT(o), m+1, rr);}}void maintain(int o){for(int i=0; i<3; i++)sum[o][i] = (sum[LEFT(o)][i]+sum[RIGHT(o)][i])%MOD;}void pushdown(int o);void update(int o, int ll, int rr, int j, int k){if(l[o]==ll && r[o]==rr){int j1,j2,j3,k1,k2,k3;j1=j;j2=(j*j1)%MOD;j3=(j*j2)%MOD;k1=k;k2=(k*k1)%MOD;k3=(k*k2)%MOD;sum[o][2] = (j3*sum[o][2])%MOD + (((j2*k1)%MOD*3)%MOD*sum[o][1])%MOD + (((j1*k2)%MOD*3)%MOD*sum[o][0])%MOD + ((rr-ll+1)*k3)%MOD;sum[o][2]%=MOD;sum[o][1] = (j2*sum[o][1])%MOD + (((j1*k1)%MOD*2)%MOD*sum[o][0])%MOD + ((rr-ll+1)*k2)%MOD;sum[o][1]%=MOD;sum[o][0] = (j1*sum[o][0])%MOD + ((rr-ll+1)*k1)%MOD;sum[o][0]%=MOD;a[o] = (a[o]*j)%MOD;b[o] = ((j*b[o])%MOD + k)%MOD;f[o] = 1;}else{if(f[o])pushdown(o);int m = MID(l[o],r[o]);if(m<ll)update(RIGHT(o), ll, rr, j, k);else if(m>=rr)update(LEFT(o), ll, rr, j, k);else{update(LEFT(o), ll, m, j, k);update(RIGHT(o), m+1, rr, j, k);}maintain(o);}}void pushdown(int o){int m = MID(l[o],r[o]);update(LEFT(o), l[o], m, a[o], b[o]);update(RIGHT(o), m+1, r[o], a[o], b[o]);a[o]=1;b[o]=0;f[o]=0;}int query(int o, int ll, int rr, int p){if(l[o]==ll && r[o]==rr)return sum[o][p];if(f[o])pushdown(o);int tmp, m=MID(l[o], r[o]);if(m<ll)tmp = query(RIGHT(o), ll, rr, p);else if(m>=rr)tmp = query(LEFT(o), ll, rr, p);else{tmp = (query(LEFT(o), ll, m, p)+query(RIGHT(o), m+1, rr, p))%MOD;}maintain(o);return tmp;}int main(){while(1){n=getnum();q=getnum();if(!(n||q))break;memset(sum, 0, sizeof(sum));memset(b, 0, sizeof(b));memset(f, 0, sizeof(f));build(1, 1, n);while(q--){op=getnum();x=getnum();y=getnum();c=getnum();if(op==1)update(1, x, y, 1, c);else if(op==2)update(1, x, y, c, 0);else if(op==3)update(1, x, y, 0, c);elseprintf("%d\n", query(1, x, y, c-1));}} return 0;}


原创粉丝点击