解题:UOJ #46 玄学

题面

二进制分组,修改把区间拆开丢在后面,合并的时候归并最后两块;查询在对应节点上二分答案

 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\n",ans);
84         }
85     }
86     return 0;
87 }
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/10513296.html
46