正题
原题是清华集训2014的玄学。
因为对于i到j操作进行询问,所以考虑对操作建一棵线段树,每一个点存有一些区间,对于每一个点,这些区间的并为



可以把这些区间转化成多个断点,每次加入一个询问操作会多两个断点,对于线段树上的一条链贡献,所以断点个数总和不超过

合并两个端点可以直接过一遍,复杂度跟断点个数相关,所以插入时间复杂度还是

查询的时候,在线段树上找到对应的节点,二分找到对应的

#include<bits/stdc++.h> #define ls now<<1 #define rs now<<1|1 using namespace std; const int N=100010; int T,n,mod,m,t=0; int A[N]; struct node{ int l,r,a,b; node operator+(const node q)const {return (node){0,0,1ll*a*q.a%mod,(1ll*b*q.a%mod+q.b)%mod};} }X; vector<node> tr[N*10]; void calc(int &a,int &b,int c,int d){ a=1ll*a*c%mod,b=1ll*c*b%mod+d; b>=mod?b-=mod:0; } void upload(int now){ int a,b,l=0; for(int i=0,j=0;i<tr[ls].size() && j<tr[rs].size();){ a=tr[ls][i].a;b=tr[ls][i].b; calc(a,b,tr[rs][j].a,tr[rs][j].b); if(tr[ls][i].r<=tr[rs][j].r){ tr[now].push_back((node){l+1,tr[ls][i].r,a,b}); l=tr[ls][i].r; if(tr[ls][i].r==tr[rs][j].r) i++,j++; else i++; } else tr[now].push_back((node){l+1,tr[rs][j].r,a,b}),l=tr[rs][j].r,j++; } } bool insert(int now,int x,int l,int r,node F){ if(l==r){ if(F.l>1) tr[now].push_back((node){1,F.l-1,1,0}); tr[now].push_back(F); if(F.r<n) tr[now].push_back((node){F.r+1,n,1,0}); return true; } int mid=(l+r)/2; if(x<=mid) {insert(ls,x,l,mid,F);return false;} else if(insert(rs,x,mid+1,r,F)) {upload(now);return true;} else return false; } node get_ans(int now,int x,int y,int k,int l,int r){ if(x==l && y==r){ int l=0,r=tr[now].size()-1; while(l<=r){ int mid=(l+r)/2; if(tr[now][mid].r<k) l=mid+1; else if(tr[now][mid].l<=k && k<=tr[now][mid].r) return tr[now][mid]; else r=mid-1; } } int mid=(l+r)/2; if(y<=mid) return get_ans(ls,x,y,k,l,mid); else if(mid<x) return get_ans(rs,x,y,k,mid+1,r); else return get_ans(ls,x,mid,k,l,mid)+get_ans(rs,mid+1,y,k,mid+1,r); } int main(){ scanf("%d %d %d",&T,&n,&mod);T=T&1; for(int i=1;i<=n;i++) scanf("%d",&A[i]); scanf("%d",&m); int tot=m; int type,x,y,a,b; long long last=0; while(m--){ scanf("%d %d %d %d",&type,&x,&y,&a); if(T) x^=last,y^=last; if(!type){ scanf("%d",&b); t++;insert(1,t,1,tot,(node){x,y,a,b}); } else{ if(T) a^=last; X=get_ans(1,x,y,a,1,tot); printf("%lld\n",last=(1ll*A[a]*X.a%mod+X.b)%mod); } } }
来源:https://blog.csdn.net/Deep_Kevin/article/details/102731674