二进制分组,修改把区间拆开丢在后面,合并的时候归并最后两块;查询在对应节点上二分答案
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=100005,Max=1e5; 6 struct a{int p,k,b;}ope[N*32]; 7 int seq[4*N],lef[4*N],rig[4*N]; 8 int n,T,t1,t2,t3,t4,op,ans,cnt,tot,mod,oni; 9 void Change(int nde,int l,int r,int ll,int rr,int k,int b) 10 { 11 if(l==r) 12 { 13 lef[nde]=cnt+1; 14 if(ll>1) ope[++cnt]=(a){ll-1,1,0}; 15 ope[++cnt]={rr,k,b}; 16 if(rr<n) ope[++cnt]=(a){n,1,0}; 17 rig[nde]=cnt; 18 } 19 else 20 { 21 int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1,l1,l2,r1,r2; 22 if(tot<=mid) Change(ls,l,mid,ll,rr,k,b); 23 else Change(rs,mid+1,r,ll,rr,k,b); 24 if(tot>=r) 25 { 26 lef[nde]=cnt+1,l1=lef[ls],l2=lef[rs],r1=rig[ls],r2=rig[rs]; 27 while(l1<=r1&&l2<=r2) 28 { 29 ope[++cnt]=(a){min(ope[l1].p,ope[l2].p), 30 1ll*ope[l1].k*ope[l2].k%mod, 31 (1ll*ope[l2].k*ope[l1].b+ope[l2].b)%mod}; 32 if(ope[l1].p==ope[l2].p) l1++,l2++; 33 else ope[l1].p<ope[l2].p?l1++:l2++; 34 } 35 rig[nde]=cnt; 36 } 37 } 38 } 39 void Calc(int nde,int tsk) 40 { 41 int l=lef[nde],r=rig[nde],p=0; 42 while(l<=r) 43 { 44 int mid=(l+r)>>1; 45 if(ope[mid].p>=tsk) p=mid,r=mid-1; 46 else l=mid+1; 47 } 48 ans=(1ll*ans*ope[p].k+ope[p].b)%mod; 49 } 50 void Query(int nde,int l,int r,int ll,int rr,int tsk) 51 { 52 if(l>rr||r<ll) 53 return ; 54 else if(l>=ll&&r<=rr) 55 Calc(nde,tsk); 56 else 57 { 58 int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1; 59 Query(ls,l,mid,ll,rr,tsk),Query(rs,mid+1,r,ll,rr,tsk); 60 } 61 } 62 int main() 63 { 64 scanf("%d",&oni),oni&=1; 65 scanf("%d%d",&n,&mod); 66 for(int i=1;i<=n;i++) 67 scanf("%d",&seq[i]); 68 scanf("%d",&T); 69 while(T--) 70 { 71 scanf("%d",&op); 72 if(op==1) 73 { 74 scanf("%d%d%d%d",&t1,&t2,&t3,&t4); 75 t1^=ans*oni,t2^=ans*oni,tot++; 76 Change(1,1,Max,t1,t2,t3,t4); 77 } 78 else 79 { 80 scanf("%d%d%d",&t1,&t2,&t3); 81 t1^=ans*oni,t2^=ans*oni,t3^=ans*oni; 82 ans=seq[t3],Query(1,1,Max,t1,t2,t3); 83 printf("%d ",ans); 84 } 85 } 86 return 0; 87 }