BZOJ 2161 布娃娃 (主席树)

题面

想了一个主席树做法

我们把每个区间的两个端点拆开

对$L,R$分别从小到大排序,分别从左到右依次把对应标号的$c_{i}$插入到权值主席树里

每次查询$p_{i}$,在排序后的$L,R$数组上分别二分找到第一个小于等于$p_{i}$的位置

那么$L,R$的主席树相减之后就是能对$p_{i}$产生贡献的区间

在主席树上二分即可

似乎平衡树和线段树的做法空间比我优秀得多..

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define N1 100010
 5 #define M1 8000100
 6 using namespace std;
 7 
 8 const int mod=19921228;
 9 struct SEG{
10 int root1[N1],root2[N1],ls[M1],rs[M1],sz[M1],tot;
11 inline void pushup(int rt){ sz[rt]=sz[ls[rt]]+sz[rs[rt]]; }
12 void update(int x,int l,int r,int r1,int &r2)
13 {
14     if((!r2)||(r1==r2)){ r2=++tot; sz[r2]=sz[r1]; ls[r2]=ls[r1]; rs[r2]=rs[r1]; }
15     if(l==r){ sz[r2]++; return; }
16     int mid=(l+r)>>1;
17     if(x<=mid) update(x,l,mid,ls[r1],ls[r2]);
18     else update(x,mid+1,r,rs[r1],rs[r2]);
19     pushup(r2);
20 }
21 int query(int K,int l,int r,int r1,int r2)
22 {
23     if(K>sz[r1]-sz[r2]) return 0;
24     if(l==r) return l;
25     int mid=(l+r)>>1;
26     if(K>sz[rs[r1]]-sz[rs[r2]]) 
27         return query(K-sz[rs[r1]]+sz[rs[r2]],l,mid,ls[r1],ls[r2]);
28     else return query(K,mid+1,r,rs[r1],rs[r2]);
29 }
30 }s;
31 
32 int n,mx;
33 int P[N1],C[N1];
34 struct node{int id,x;}L[N1],R[N1];
35 int cmp(node s1,node s2){ return s1.x<s2.x; }
36 
37 void make()
38 {
39     int Padd, Pfirst, Pmod, Pprod, Cadd, Cfirst, Cmod, Cprod, Ladd, Lfirst, Lmod, Lprod, Radd, Rfirst, Rmod, Rprod, i; 
40     scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",&Padd, &Pfirst, &Pmod, &Pprod, &Cadd, &Cfirst, &Cmod, &Cprod, &Ladd, &Lfirst, &Lmod, &Lprod, &Radd, &Rfirst, &Rmod, &Rprod);
41     P[1]=Pfirst%Pmod; for(i=2;i<=n;i++) P[i]=(1ll*P[i-1]*Pprod+Padd+i)%Pmod;
42     C[1]=Cfirst%Cmod; for(i=2;i<=n;i++) C[i]=(1ll*C[i-1]*Cprod+Cadd+i)%Cmod, mx=max(mx,C[i]); mx=max(mx,C[1]);
43     L[1].x=Lfirst%Lmod; for(i=2;i<=n;i++) L[i].x=(1ll*L[i-1].x*Lprod+Ladd+i)%Lmod;
44     R[1].x=Rfirst%Rmod; for(i=2;i<=n;i++) R[i].x=(1ll*R[i-1].x*Rprod+Radd+i)%Rmod;
45     for(i=1;i<=n;i++){ L[i].id=i, R[i].id=i; if(L[i].x>R[i].x) swap(L[i].x,R[i].x); }
46     sort(L+1,L+n+1,cmp); sort(R+1,R+n+1,cmp);
47     for(i=1;i<=n;i++) s.update(C[L[i].id],0,mx,s.root1[i-1],s.root1[i]);
48     for(i=1;i<=n;i++) s.update(C[R[i].id],0,mx,s.root2[i-1],s.root2[i]);
49 }
50 int ans[N1];
51 
52 int main()
53 {
54     scanf("%d",&n);
55     make();
56     int i,j,l,r,mid,xl,xr,ret=0;
57     for(i=1;i<=n;i++)
58     {
59         if(P[i]<L[1].x||P[i]>R[n].x) continue;
60         l=1,r=n,xl=0;
61         while(l<=r) 
62         {
63             mid=(l+r)>>1;
64             if(L[mid].x<=P[i]) xl=mid,l=mid+1;
65             else r=mid-1;
66         } 
67         l=1,r=n,xr=0;
68         while(l<=r) 
69         {
70             mid=(l+r)>>1;
71             if(R[mid].x<=P[i]-1) xr=mid,l=mid+1;
72             else r=mid-1;
73         } 
74         ans[i]=s.query(i,0,mx,s.root1[xl],s.root2[xr]);
75         (ret+=ans[i])%=mod;
76     }
77     printf("%d
",ret);
78     return 0;
79 }
原文地址:https://www.cnblogs.com/guapisolo/p/10357488.html