• 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 }
  • 相关阅读:
    宏定义抽取单例
    谓词基本使用
    Xcode静态分析工具--Analyze
    [转载]CocoaPods管理第三方开源框架
    @import--iOS7新关键字
    iOS手势识别
    UINavigationController
    JSON解析--原生&AFN
    UITabBarController
    iOS APP EuclidStudy Service Support
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10357488.html
Copyright © 2020-2023  润新知