2013杭州邀请赛的题目,当时我负责写这道题。然后被我写翔了。。。
现在组织好代码重写,幸运1A了。代码能力还是太弱。
题意:
三种操作,会询问[x,y]的一次方和,平方和,次方和
思路:
推推公式,开三个懒标记,累乘(mul),累乘累加(add),赋值(asi)。主要注意如何pushdown,还有要组织好代码。
sum[0]表示一次方的和,以此类推。
注意:更新必须从sum[2]~sum[0]
公式:
update:
p=1
+c: sum[0] + n*c
*c: sum[0]*c
=c: n*c
p=2
+c: sum[1] + n*c^2 + 2*c*sum[0]
*c: sum[1]*c^2
=c: n*c^2
p=3
+c: sum[2] + n*c^3 + 3*c*sum[1] + 3*c^2 *sum[0]
*c: sum[2]*c^3
=c: n*c^3
pushdown:
p=1
mul*sum[0] + n*add
p=2
mul^2 * sum[1] + 2*mul*sum[0]*add + n*add^2
p=3
mul^3 * sum[2] + 3*mul^2 * sum[1]*add + 3*mul*sum[0]*add^2 + n*add^3
代码:
#include <algorithm> #include <iostream> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <string> #include <math.h> #include <vector> #include <queue> #include <stack> #include <cmath> #include <list> #include <set> #include <map> using namespace std; /*-------------------------Template----*/ #define N 100010 #define E 100010 #define ll long long #define CB(x) ((x)*(x)*(x)) #define SQ(x) ((x)*(x)) #define ALL(x) x.begin(),x.end() #define CLR(x,a) memset(x,a,sizeof(x)) #define maxAry(a,n) max_element(a,a+(n)) #define minAry(a,n) min_element(a,a+(n)) typedef pair<int,int> PI; const int INF=0x3fffffff; const int PRIME =999983; const int MOD =10007; const int MULTI =1000000007; const double EPS=1e-9; inline bool isodd(int x){return x&1;} inline bool isodd(ll x) {return x&1;} /*----------------------end Template----*/ class SegTree{ #define lson (rt<<1) #define rson (rt<<1|1) #define sgt seg[rt] #define rtl seg[rt].l #define rtr seg[rt].r private: struct segment{ int l,r,sum[3],asi,add,mul; }seg[N<<2]; public: void setMark(int op,int c,int rt) { if(op==1) sgt.add+=c; else if(op==2) sgt.mul*=c, sgt.add*=c; else sgt.asi=c, sgt.mul=1, sgt.add=0; sgt.mul%=MOD, sgt.add%=MOD; } void change(int op,ll c,int rt) { int n=rtr-rtl+1; switch(op){ case 1: //+ sgt.sum[2]+=(n*CB(c) + 3*c*sgt.sum[1] + 3*SQ(c)*sgt.sum[0])%MOD; sgt.sum[1]+=(n*SQ(c) + 2*c*sgt.sum[0])%MOD; sgt.sum[0]+=(n*c)%MOD; break; case 2: //* sgt.sum[2]*=CB(c)%MOD; sgt.sum[1]*=SQ(c)%MOD; sgt.sum[0]*=c; break; default://= sgt.sum[2]=n*CB(c)%MOD; sgt.sum[1]=n*SQ(c)%MOD; sgt.sum[0]=n*c%MOD; } sgt.sum[2]%=MOD; sgt.sum[1]%=MOD; sgt.sum[0]%=MOD; } void refresh(ll mul,ll add,int rt) { int n=rtr-rtl+1; sgt.sum[2]=(CB(mul)*sgt.sum[2] + 3*SQ(mul)*sgt.sum[1]*add + 3*mul*sgt.sum[0]*SQ(add) + n*CB(add))%MOD; sgt.sum[1]=(SQ(mul)*sgt.sum[1] + 2*mul*sgt.sum[0]*add + n*SQ(add))%MOD; sgt.sum[0]=(mul*sgt.sum[0] + n*add)%MOD; sgt.sum[2]%=MOD; sgt.sum[1]%=MOD; sgt.sum[0]%=MOD; sgt.mul=(sgt.mul*mul)%MOD; sgt.add=(sgt.add*mul+add)%MOD; } void pushup(int rt) { for(int i=0;i<3;i++) sgt.sum[i]=(seg[lson].sum[i]+seg[rson].sum[i])%MOD; } void pushdown(int rt) { if(sgt.asi){ change(3,sgt.asi,lson); change(3,sgt.asi,rson); setMark(3,sgt.asi,lson); setMark(3,sgt.asi,rson); sgt.asi=0; } if(sgt.mul!=1 || sgt.add){ refresh(sgt.mul,sgt.add,lson); refresh(sgt.mul,sgt.add,rson); sgt.mul=1; sgt.add=0; } } void build(int l,int r,int rt) { rtl=l, rtr=r; CLR(sgt.sum,0); sgt.add=0; sgt.mul=1; sgt.asi=0; if(l==r) return ; int mid=(rtl+rtr)>>1; build(l,mid,lson); build(mid+1,r,rson); } void update(int op,int c,int L,int R,int rt) { if(L<=rtl && rtr<=R){ change(op,c,rt); setMark(op,c,rt); return ; } int mid=(rtl+rtr)>>1; pushdown(rt); if(L<=mid) update(op,c,L,R,lson); if(mid<R) update(op,c,L,R,rson); pushup(rt); } int query(int op,int L,int R,int rt) { int ans=0; if(L<=rtl && rtr<=R) return sgt.sum[op-1]; int mid=(rtl+rtr)>>1; pushdown(rt); if(L<=mid) ans+=query(op,L,R,lson); if(mid<R) ans+=query(op,L,R,rson); return ans%MOD; } }T; int main() { int n,m,l,r,c,op; while(scanf("%d%d",&n,&m),n||m){ T.build(1,n,1); while(m--){ scanf("%d%d%d%d",&op,&l,&r,&c); if(1<=op && op<=3){ T.update(op,c,l,r,1); }else{ printf("%d\n", T.query(c,l,r,1)); } } } return 0; }