• BZOJ 1503 郁闷的出纳员


    一开始潜意识就认为是splay模板,打了140+行,还调了很久(自己码力太弱了)

    然后听学长说不用打标记,可以存全局的增减值,于是写了一个60-的权值线段树,非常快且好看地就A掉了

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define lc ch[x][0]
    #define rc ch[x][1]
    const int maxn=100005;
    using namespace std;
    int ans,tot,root,n,mi,x,y,v[maxn],cnt[maxn],ch[maxn][2],p[maxn],sz[maxn],lz[maxn];
    char s[5];
    void update(int x) {sz[x]=sz[lc]+sz[rc]+cnt[x];}
    void rotate(int x){
        int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
        if(z) {ch[z][y==ch[z][1]]=x;} p[x]=z;
        ch[y][l]=ch[x][r]; p[ch[y][l]]=y;
        ch[x][r]=y; p[y]=x;
        update(y); update(x);
    }
    void down(int x){
      if(!lz[x]) return;
      if(lc) {v[lc]+=lz[x]; lz[lc]+=lz[x];}
      if(rc) {v[rc]+=lz[x]; lz[rc]+=lz[x];}
      lz[x]=0;
    }
    void splay(int x){
        if(x==root) return;
        static int s[maxn],top;
        for(int i=x;i;i=p[i]) s[++top]=i;
        while(top) down(s[top--]);
        for(;p[x];rotate(x)){
         int y=p[x],z=p[y];
         if(z){
          ((y==ch[z][1])^(z==ch[y][1]))?rotate(x):rotate(y);
         }    
        }
        root=x;
    }
    int pre(){
        x=root; x=lc;
        while(rc) x=rc;
        return x;
    }
    int rak(int k){ 
      for(x=root;x;){
          if(v[x]==k) {
         splay(x); 
         return x;
        } 
          down(x);
          if(v[x]<k) x=rc;
          else x=lc;
      }
    }
    int kth(int k){
      for(x=root;x;){
          if(k>=sz[lc]+1&&k<=sz[lc]+cnt[x]) return x;
          down(x);
          if(k<=sz[lc]) x=lc;
          else k-=(sz[lc]+cnt[x]),x=rc;
      }
    }
    int kth2(int k){
      for(x=root;x;){
          if(k>=sz[rc]+1&&k<=sz[rc]+cnt[x]) return x;
          down(x);
          if(k<=sz[rc]) x=rc;
          else k-=(sz[rc]+cnt[x]),x=lc;
      }
    }
    void del(int y){
      x=rak(y); x=root;
      if(cnt[x]>1) {cnt[x]--;update(x);return;}
      if(!lc) root=rc,p[root]=0;
      else if(!rc) root=lc,p[root]=0;
      else {
        int z=pre();
        splay(z);
        x=root;
        if(ch[rc][1]) p[ch[rc][1]]=x;
        rc=ch[rc][1];
        update(x);
      }
    }
    void insert(int y){
      x=root;
      int l=0,fa=0;
      if(!x) {
          root=++tot;
          v[root]=y;
          sz[tot]=cnt[tot]=1;
          return;
      }
      for(;;){
         if(!x){
         x=++tot;
         p[x]=fa;
         v[x]=y;
         ch[fa][l]=x;
         sz[x]=cnt[x]=1;
         splay(x);
         return;
       }
       down(x);
       if(v[x]==y){
         cnt[x]++;
         splay(x);
         return;
       }
       if(v[x]>y) fa=x,l=0,x=lc;
       else fa=x,l=1,x=rc;
      }
    }
    int main()
    { 
       scanf("%d%d",&n,&mi);
       while(n--){
         scanf("%s%d",s,&y);
         if(s[0]=='I') {if(y>=mi) insert(y);}
         else if(s[0]=='A') {v[root]+=y;lz[root]+=y;}
         else if(s[0]=='S'){
             insert(mi+y); 
            x=root;
            ans+=sz[lc];
            p[lc]=0; lc=0; 
            update(x);
            del(mi+y);
            v[root]-=y;
            lz[root]-=y;
         }
         else if(s[0]=='F') {
         if(y>sz[root]) cout<<"-1"<<endl;
         else printf("%d
    ",v[kth2(y)]);}
       }
       printf("%d
    ",ans);
       return 0;
    }
    splay

    很神奇的是这个splay版的如果不写Kth2而是直接用kth找就会WA?一直没找出是什么问题。。

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    #define mid ((l+r)>>1)
    const int maxn=100005;
    const int nn=1e9;
    using namespace std;
    int n,y,mi,root,tot,ans,sg[maxn<<3],ls[maxn<<3],rs[maxn<<3],lzz;
    char s[5];
    void add(int &x,int l,int r,int v){
       if(!x) x=++tot;
       if(l==r) {sg[x]++;return;}
       if(v<=mid) add(ls[x],l,mid,v);
       else add(rs[x],mid+1,r,v);
       sg[x]=sg[ls[x]]+sg[rs[x]];
    }
    int query(int x,int l,int r,int k){
      if(l==r) return l+lzz;
      if(sg[ls[x]]>=k) return query(ls[x],l,mid,k);
      else return query(rs[x],mid+1,r,k-sg[ls[x]]);
    }
    void check(int x,int l,int r,int v){
       if(ls[x]){
        if(mid<v) {ans+=sg[ls[x]]; ls[x]=0;}
        else check(ls[x],l,mid,v);
       }
       if(rs[x]) if(mid+1<v) check(rs[x],mid+1,r,v); 
       sg[x]=sg[ls[x]]+sg[rs[x]];
    }
    int main()
    { 
       scanf("%d%d",&n,&mi);
       while(n--){
         scanf("%s%d",s,&y);
         if(s[0]=='I') {
             if(y<mi) /*ans++*/;
             else{
               add(root,-nn,nn,y-lzz);
            }
         }
         else if(s[0]=='A') lzz+=y;
         else if(s[0]=='S'){
             lzz-=y;
             check(root,-nn,nn,mi-lzz);
         }
         else if(s[0]=='F') {
             if(y>sg[root]) cout<<"-1"<<endl;
              else printf("%d
    ",query(1,-nn,nn,sg[root]-y+1));
         }
       }
       printf("%d
    ",ans);
       return 0;
    }
    权值线段树
  • 相关阅读:
    python学习笔记1--datetime的使用
    python学习笔记2--子类父类继承时的参数传递
    python学习笔记1--错误,异常,调试
    JS同异步编程
    AMD /CMD
    i++ && ++i
    将url问号后面的参数变成对象
    字符串的常用方法
    函数 && 函数运行机制
    Math数学函数及常用方法
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7475065.html
Copyright © 2020-2023  润新知