hdu 4578 线段树
思路:本来写了一个比较短的代码,并且各函数间的重用性比较高,就是结果悲剧的超时了...就是保证每个区间只有一种操作,那么更新时就要更新子节点的子节点,需要递归更新,结果是可想而知。其实这种做法是可以过得,只要将复杂度转移到求和上去(测试数据对求和操作应该要求不严)。但那样就不能直接保存p的三种情况值,因为这样会使得常数级非常大,超时。
所以就要找到多重操作并存的方法。对于置为c,这个容易解决。关键是加和乘。思路见代码注释
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define lson(x) x<<1 #define rson(x) x<<1|1 #define Maxn 100010 #define mod 10007 using namespace std; struct Tree{ int l,r; __int64 s[4],c,add,mul;//add是对子节点的加量,mul是对子节点的乘量,并不是对本节点的操作,c是判断是否置为c int mid() { return (l+r)>>1; } }tree[Maxn*4]; int ans; void BuildTree(int l,int r,int po) { tree[po].l=l,tree[po].r=r,tree[po].c=0,tree[po].s[2]=tree[po].s[3]=tree[po].s[1]=0,tree[po].c=tree[po].add=0,tree[po].mul=1; if(l==r) return ; int mid=tree[po].mid(); BuildTree(l,mid,lson(po)); BuildTree(mid+1,r,rson(po)); } void calculate(int po,int ty,__int64 c) {//根据平方式和三次方式算出来的相对应一次式的增量 if(ty==1){ tree[po].s[3]+=3*c*tree[po].s[2]+3*c*c *tree[po].s[1] +c*c*c*(tree[po].r-tree[po].l+1); tree[po].s[2]+=2*tree[po].s[1]*c +c*c*(tree[po].r-tree[po].l+1); tree[po].s[1]+=c*(tree[po].r-tree[po].l+1); tree[po].add+=c; tree[po].add%=mod; } if(ty==2){ tree[po].s[1]*=c; tree[po].s[2]*=c*c; tree[po].s[3]*=c*c*c; tree[po].add=tree[po].add*c%mod; tree[po].mul=tree[po].mul*c%mod; } if(ty==3){ tree[po].s[1]=c*(tree[po].r-tree[po].l+1) ; tree[po].s[2]=c*c*(tree[po].r-tree[po].l+1) ; tree[po].s[3]=c*c*c*(tree[po].r-tree[po].l+1) ; tree[po].add=0; tree[po].mul=1; tree[po].c=c; } tree[po].s[3]%=mod; tree[po].s[2]%=mod; tree[po].s[1]%=mod; } void down(int po) { if(tree[po].c){//如果遇到的是值为c,那么具有优先权将其子节点全置为c. tree[lson(po)].add=tree[rson(po)].add=0; tree[lson(po)].mul=tree[rson(po)].mul=1; tree[lson(po)].c=tree[rson(po)].c=tree[po].c; tree[lson(po)].s[1]=tree[po].c*(tree[lson(po)].r-tree[lson(po)].l+1) ; tree[lson(po)].s[2]=tree[po].c*tree[po].c *(tree[lson(po)].r-tree[lson(po)].l+1) ; tree[lson(po)].s[3]=tree[po].c*tree[po].c *tree[po].c *(tree[lson(po)].r-tree[lson(po)].l+1) ; tree[rson(po)].s[1]=tree[po].c*(tree[rson(po)].r-tree[rson(po)].l+1) ; tree[rson(po)].s[2]=tree[po].c*tree[po].c *(tree[rson(po)].r-tree[rson(po)].l+1) ; tree[rson(po)].s[3]=tree[po].c*tree[po].c *tree[po].c *(tree[rson(po)].r-tree[rson(po)].l+1) ; tree[po].c=0; tree[lson(po)].s[1]%=mod; tree[lson(po)].s[2]%=mod; tree[lson(po)].s[3]%=mod; tree[rson(po)].s[1]%=mod; tree[rson(po)].s[2]%=mod; tree[rson(po)].s[3]%=mod; } if(tree[po].add != 0 || tree[po].mul != 1) { //对左儿子进行处理 //本来的x变成了x*tree[po].mul; //将乘法的优先权置为比加高,那么当子节点加过一个值m,当再次对其进行乘y的时候,其实就是加了m*y,乘法同理。 tree[lson(po)].add=(tree[po].mul*tree[lson(po)].add+tree[po].add)%mod;//修改子节点的加法增量 tree[lson(po)].mul=tree[lson(po)].mul*tree[po].mul%mod;//修改乘法增量 //下面的求和其实就是将ty==1和ty==2一起算了,其乘法的优先级高,故x显示被乘了tree[po].mul; tree[lson(po)].s[3]=tree[po].mul*tree[po].mul*tree[po].mul*tree[lson(po)].s[3]; tree[lson(po)].s[3]=(tree[lson(po)].s[3]+3*tree[po].mul*tree[po].mul*tree[po].add*tree[lson(po)].s[2]); tree[lson(po)].s[3]=(tree[lson(po)].s[3]+3*tree[po].mul*tree[po].add*tree[po].add*tree[lson(po)].s[1]); tree[lson(po)].s[3]=(tree[lson(po)].s[3]+(tree[lson(po)].r-tree[lson(po)].l+1)*tree[po].add*tree[po].add*tree[po].add); tree[lson(po)].s[2]=(tree[po].mul*tree[po].mul*tree[lson(po)].s[2]+2*tree[po].add*tree[po].mul*tree[lson(po)].s[1]+(tree[lson(po)].r-tree[lson(po)].l+1)*tree[po].add*tree[po].add) ; tree[lson(po)].s[1]=(tree[lson(po)].s[1]*tree[po].mul+(tree[lson(po)].r-tree[lson(po)].l+1)*tree[po].add); tree[lson(po)].s[1]%=mod; tree[lson(po)].s[2]%=mod; tree[lson(po)].s[3]%=mod; //对右儿子进行处理,同左儿子 tree[rson(po)].add=(tree[po].mul*tree[rson(po)].add+tree[po].add)%mod; tree[rson(po)].mul=tree[rson(po)].mul*tree[po].mul%mod; tree[rson(po)].s[3]=tree[po].mul*tree[po].mul*tree[po].mul*tree[rson(po)].s[3]; tree[rson(po)].s[3]=(tree[rson(po)].s[3]+3*tree[po].mul*tree[po].mul*tree[po].add*tree[rson(po)].s[2]); tree[rson(po)].s[3]=(tree[rson(po)].s[3]+3*tree[po].mul*tree[po].add*tree[po].add*tree[rson(po)].s[1]); tree[rson(po)].s[3]=(tree[rson(po)].s[3]+(tree[rson(po)].r-tree[rson(po)].l+1)*tree[po].add*tree[po].add*tree[po].add); tree[rson(po)].s[2]=(tree[po].mul*tree[po].mul*tree[rson(po)].s[2]+2*tree[po].add*tree[po].mul*tree[rson(po)].s[1]+(tree[rson(po)].r-tree[rson(po)].l+1)*tree[po].add*tree[po].add) ; tree[rson(po)].s[1]=(tree[rson(po)].s[1]*tree[po].mul+(tree[rson(po)].r-tree[rson(po)].l+1)*tree[po].add); tree[rson(po)].s[1]%=mod; tree[rson(po)].s[2]%=mod; tree[rson(po)].s[3]%=mod; tree[po].add = 0; tree[po].mul = 1; } } void update(int l,int r,int ty,int c,int po) { if(l<=tree[po].l&&r>=tree[po].r) { calculate(po,ty,(__int64)c);//计算本节点 return ; } down(po); int mid=tree[po].mid(); if(r<=mid) update(l,r,ty,c,lson(po)); else if(l>=mid+1) update(l,r,ty,c,rson(po)); else{ update(l,mid,ty,c,lson(po)); update(mid+1,r,ty,c,rson(po)); } tree[po].s[1]=(tree[lson(po)].s[1]+tree[rson(po)].s[1])%mod; tree[po].s[2]=(tree[lson(po)].s[2]+tree[rson(po)].s[2])%mod; tree[po].s[3]=(tree[lson(po)].s[3]+tree[rson(po)].s[3])%mod; } void get_Sum(int l,int r,int p,int po) { if(l<=tree[po].l&&r>=tree[po].r) { ans+=tree[po].s[p]; ans%=mod; return ; } down(po); int mid=tree[po].mid(); if(r<=mid) get_Sum(l,r,p,lson(po)); else if(l>=mid+1) get_Sum(l,r,p,rson(po)); else{ get_Sum(l,mid,p,lson(po)); get_Sum(mid+1,r,p,rson(po)); } tree[po].s[1]=(tree[lson(po)].s[1]+tree[rson(po)].s[1])%mod; tree[po].s[2]=(tree[lson(po)].s[2]+tree[rson(po)].s[2])%mod; tree[po].s[3]=(tree[lson(po)].s[3]+tree[rson(po)].s[3])%mod; } int main() { int n,i,j,l,r,c,p,m,x; while(scanf("%d%d",&n,&m)!=EOF,n&&m) { BuildTree(1,n,1); for(i=1;i<=m;i++) { scanf("%d%d%d%d",&x,&l,&r,&c); if(x==1){ update(l,r,1,c,1); } if(x==2){ update(l,r,2,c,1); } if(x==3){ update(l,r,3,c,1); } if(x==4){ ans=0; get_Sum(l,r,c,1); printf("%d\n",ans); } } } return 0; }