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\n",ret); 78 return 0; 79 }