5 5 3 3 5 7 1 2 4 4 4 1 5 2 2 2 5 8 4 3 5 3 0 0
307 7489
线段树:有set, mul,add三个标记。
当set时,把mul,add初始化。
mul操作时,可以把mul*mul, add*mul可以直接合并。然后每个区间先做乘法,然后做加法
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 300000 #define ll long long int sum[maxn][3]; int mul[maxn],add[maxn],val[maxn]; int lc[maxn],rc[maxn],set[maxn]; int mod = 10007; int cnt; void init(){ cnt = 1; memset(sum,0,sizeof(sum)); memset(lc,0,sizeof(lc)); memset(rc,0,sizeof(rc)); memset(val,0,sizeof(val)); for(int i = 0;i < maxn; i++) mul[i] = 1; memset(add,0,sizeof(add)); memset(set,0,sizeof(set)); } void update(int u,int l,int r){ if(l == r || u == 0) return ; int len = (r-l+1)%mod; if(set[u] != 0){ int num = set[u]*set[u]%mod; sum[u][0] = set[u]*len%mod; sum[u][1] = num*len%mod; sum[u][2] = num*set[u]%mod*len%mod; return ; } int s1 = (sum[lc[u]][0] + sum[rc[u]][0])%mod; int s2 = (sum[lc[u]][1] + sum[rc[u]][1])%mod; int s3 = (sum[lc[u]][2] + sum[rc[u]][2])%mod; if(mul[u] > 1){ s1 = (ll)s1*mul[u]%mod; s2 = (ll)s2*mul[u]*mul[u]%mod; s3 = (ll)s3*mul[u]*mul[u]*mul[u]%mod; } if(add[u] != 0){ ll a1 = add[u],a2= a1*a1,a3=a2*a1; sum[u][0] = (ll)(s1 + a1*len)%mod; sum[u][1] = (ll)(s2+2*s1*a1+a2*len)%mod; sum[u][2] = ((ll)s3+3*s2*a1+3*s1*a2+a3*len)%mod; } else sum[u][0] = s1,sum[u][1] = s2,sum[u][2] = s3; } void pushdown(int u,int l,int r,int op,int num){ if(u == 0) return ; if(l == r){ if(op == 1) val[u] = (val[u] + num) % mod; else if(op == 2) val[u] = val[u] * num % mod; else if(op == 3) val[u] = num; sum[u][0] = val[u]; sum[u][1] = (ll)val[u]*val[u]%mod; sum[u][2] = (ll)val[u]*val[u]*val[u]%mod; return ; } if(op == 3){ set[u] = num; add[u] = 0; mul[u] = 1; update(u,l,r); return ; } int mid = (l+r)/2; if(set[u] != 0){ pushdown(lc[u],l,mid,3,set[u]); pushdown(rc[u],mid+1,r,3,set[u]); set[u] = 0; } if(op == 2){ mul[u] = mul[u]*num%mod; add[u] = add[u]*num%mod; } if(op == 1){ if(num == 0){ if(mul[u] != 1){ pushdown(lc[u],l,mid,2,mul[u]); pushdown(rc[u],mid+1,r,2,mul[u]); mul[u] = 1; } if(add[u] > 0){ pushdown(lc[u],l,mid,1,add[u]); pushdown(rc[u],mid+1,r,1,add[u]); } add[u] = 0; } else add[u] = (add[u]+num)%mod; } update(u,l,r); } void build(int u,int l,int r){ if(l == r) return ; int mid = (l+r)/2; lc[u] = cnt++; rc[u] = cnt++; build(lc[u],l,mid); build(rc[u],mid+1,r); } int query(int u,int l,int r,int L,int R,int ty){ if(l == L && R == r) return sum[u][ty]; pushdown(u,l,r,1,0); int mid = (l+r)/2; int ans = 0; if(mid < L) ans = query(rc[u],mid+1,r,L,R,ty); else if(mid >= R) ans = query(lc[u],l,mid,L,R,ty); else ans = query(lc[u],l,mid,L,mid,ty)+query(rc[u],mid+1,r,mid+1,R,ty); update(u,l,r); return ans%mod; } void work(int u,int l,int r,int L,int R,int op,int num){ if(l == L && R == r){ pushdown(u,l,r,op,num); return ; } pushdown(u,l,r,1,0); int mid = (l+r)/2; if(mid < L) work(rc[u],mid+1,r,L,R,op,num); else if(mid >= R) work(lc[u],l,mid,L,R,op,num); else work(lc[u],l,mid,L,mid,op,num),work(rc[u],mid+1,r,mid+1,R,op,num); update(u,l,r); } int main(){ int n,m; //freopen("4578.in","r",stdin); //freopen("4578.out","w",stdout); while(scanf("%d%d",&n,&m),n+m){ int op,l,r,num; init(); cnt++; build(1,1,n); while(m--){ scanf("%d%d%d%d",&op,&l,&r,&num); if(op != 4) work(1,1,n,l,r,op,num%mod); else printf("%d\n",query(1,1,n,l,r,num-1)); } } return 0; }