hdu 4578 Transformation

来源:互联网 发布:怎么比对两列数据 编辑:程序博客网 时间:2024/05/16 05:24

http://acm.hdu.edu.cn/showproblem.php?pid=4578


又做了一道好题。。

有三种操作:

1 a b c [a,b]加上c

2 a b c [a,b]乘上c

3 a b c [a,b]变为c

4 a b c 求[a,b]的c次方和(1<=c<=3)


这题首先需要解决的第一个问题是加上或乘上一个数对这个区间的c次方和分别产生什么改变,很简单,一化简就能得到。

第二个问题是当一段区间上既有乘又有加的lazy时应该怎么向下推送,因为一段区间上只能有一个lazy,我起初做的是先将有lazy的标记向下传,直到不冲突为止,然后更新这个区间的lazy,后来无数次的wa。代码太长了,简直无法debug。

同学说要找到这两个lazy的关系,即可以把每个数看做mult * x + add。加上一个数y时,add+= y,乘上一个数y时,mult *= y,add *= y。这样就解决了先加后乘和先乘后加的问题了,感觉好机智,mark。


#include <stdio.h>#include <iostream>#include <map>#include <set>#include <list>#include <stack>#include <vector>#include <math.h>#include <string.h>#include <queue>#include <string>#include <stdlib.h>#include <algorithm>//#define LL long long#define LL __int64#define eps 1e-12#define PI acos(-1.0)using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 100010;const int mod = 10007;struct node{    int l,r;    int mult,add;    int s[4];} tree[maxn*4];void build(int v, int l, int r){tree[v].l = l;tree[v].r = r;tree[v].mult = 1;tree[v].add = 0;tree[v].s[1] = tree[v].s[2] = tree[v].s[3] = 0;if(l == r)return;int mid = (l+r)>>1;build(v*2,l,mid);build(v*2+1,mid+1,r);}void cal(int v,int mult, int add){int len = tree[v].r - tree[v].l + 1;tree[v].s[1] = tree[v].s[1] * mult%mod;tree[v].s[2] = tree[v].s[2] * mult%mod*mult%mod;tree[v].s[3] = tree[v].s[3] * mult%mod*mult%mod*mult%mod;tree[v].mult = (tree[v].mult * mult)%mod;tree[v].add = (tree[v].add * mult)%mod;tree[v].s[3] = (tree[v].s[3] + 3*add%mod*add%mod*tree[v].s[1]%mod)%mod;tree[v].s[3] = (tree[v].s[3] + 3*add%mod*tree[v].s[2]%mod)%mod;tree[v].s[3] = (tree[v].s[3] + len*add%mod*add%mod*add%mod)%mod;tree[v].s[2] = (tree[v].s[2] + 2*add%mod*tree[v].s[1]%mod)%mod;tree[v].s[2] = (tree[v].s[2] + len*add%mod*add%mod)%mod;tree[v].s[1] = (tree[v].s[1] + len*add%mod)%mod;tree[v].add = (tree[v].add + add)%mod;}void push_down(int v){if(tree[v].l == tree[v].r)return;cal(v*2,tree[v].mult,tree[v].add);cal(v*2+1,tree[v].mult,tree[v].add);tree[v].mult = 1;tree[v].add = 0;}void push_up(int v){int ls = v*2,rs = v*2+1;tree[v].s[1] = (tree[ls].s[1] + tree[rs].s[1])%mod;tree[v].s[2] = (tree[ls].s[2] + tree[rs].s[2])%mod;tree[v].s[3] = (tree[ls].s[3] + tree[rs].s[3])%mod;}void update(int v, int l, int r, int mult, int add){if(tree[v].l == l && tree[v].r == r){cal(v,mult,add);return;}push_down(v);int mid = (tree[v].l + tree[v].r) >> 1;if(r <= mid)update(v*2,l,r,mult,add);else if(l > mid)update(v*2+1,l,r,mult,add);else{update(v*2,l,mid,mult,add);update(v*2+1,mid+1,r,mult,add);}push_up(v);}int query(int v, int l, int r,int p){if(tree[v].l == l && tree[v].r == r){return tree[v].s[p];}push_down(v);int mid = (tree[v].l + tree[v].r) >> 1;if(r <= mid)return query(v*2,l,r,p);else if(l > mid)return query(v*2+1,l,r,p);elsereturn (query(v*2,l,mid,p) + query(v*2+1,mid+1,r,p))%mod;}int main(){    int n,m;    int op,x,y,c;    while(~scanf("%d %d",&n,&m))    {        if(n == 0 && m == 0) break;        build(1,1,n);        while(m--)        {            scanf("%d %d %d %d",&op,&x,&y,&c);            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);            else                printf("%d\n",query(1,x,y,c)%mod);        }    }    return 0;}


0 0
原创粉丝点击