zoukankan      html  css  js  c++  java
  • 【NOIP2017】列队 splay

    当年太菜了啊,连$60$分的暴力都没拿满,只打了一个$30$分的。

    考虑到这题最多只会询问到$30W$个点,且整个矩阵会去到$30W imes 30W$,显然不能将所有的点存下来。

    对于每一行(除最右侧的数)我们维护一个$splay$,存储该位置的值,考虑到矩阵很大肯定不能全部开下,我们用一个节点存储一个区间(详情见代码)

    这样会发现最右侧一列被吃了,所以我们还要维护一个$splay$去存储这一列的数。

    对于一组询问$(x,y)$,当$y=m$时,那么显然直接在最右侧的$slpay$上删去某个位置的值,然后丢到这个$splay$的末尾即可。

    当$y≠m$时,我们就在第x课splay中将包含有y这个数的区间拎出来,砍成三段(详情见代码),从这个$splay$中删去这个数字,然后重复$y=m$时所做的操作。

    这么做的时间复杂度是$O(m log n+n log m+q log n+q log m)$,常数有点大但反正过了。

    代码貌似不短qwq,可能是我的写法比较垃圾

      1 #include<bits/stdc++.h>
      2 #define M 500005
      3 #define L long long
      4 #define lc(x) ch[x][0]
      5 #define rc(x) ch[x][1]
      6 using namespace std;
      7 
      8 int ch[M*8][2]={0},siz[M*8]={0},fa[M*8]={0},cnt[M*8]={0};L a[M*8]={0};
      9 int rt[M]={0},rty=0,use=0;
     10 L n,m,q,numuse;
     11 void pushup(int x){siz[x]=siz[lc(x)]+siz[rc(x)]+cnt[x];}
     12 void rotate(int x,int &k){
     13     int y=fa[x],z=fa[y];
     14     int l=lc(y)!=x,r=l^1;
     15     if(y==k) k=x;
     16     else{
     17         if(lc(z)==y) lc(z)=x;
     18         else rc(z)=x;
     19     }
     20     fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
     21     ch[y][l]=ch[x][r]; ch[x][r]=y;
     22     pushup(y); pushup(x);
     23 }
     24 void splay(int x,int &k){
     25     while(x!=k){
     26         int y=fa[x],z=fa[y];
     27         if(y!=k){
     28             if((lc(z)==y)^(lc(y)==x)) rotate(x,k);
     29             else rotate(y,k);
     30         }
     31         rotate(x,k);
     32     }
     33 }
     34 
     35 int find(int x,int k){
     36     if(!x) return 0;
     37     if(k<=siz[lc(x)]) return find(lc(x),k);
     38     if(k<=siz[lc(x)]+cnt[x]) return x;
     39     return find(rc(x),k-siz[lc(x)]-cnt[x]);
     40 }
     41 void ins(int &x,int k,int id){
     42     if(!x) {x=id; pushup(id); return;}
     43     if(k<=siz[lc(x)]) ins(lc(x),k,id),fa[lc(x)]=x;
     44     else ins(rc(x),k-siz[lc(x)]-cnt[x],id),fa[rc(x)]=x;
     45     pushup(x);
     46 }
     47 void merge(int x,int y,int &rt){
     48     //合并两个splay
     49     if(!x) {rt=y; return;}
     50     if(!y) {rt=x; return;}
     51     rt=x; fa[x]=0;
     52     while(rc(x)) x=rc(x);
     53     rc(x)=y; fa[y]=x;
     54     splay(y,rt);
     55 }
     56 
     57 int query(int x,int y){
     58     //询问x,y位置的值,并且从splay中分离出来 
     59     int now=find(rt[x],y); 
     60     if(!now) return 0;
     61     splay(now,rt[x]);//找出点的位置 
     62     if(cnt[now]==1) return now; 
     63     int lch=lc(now),rch=rc(now);
     64     int cntl=y-siz[lc(now)];
     65     if(cntl-1){
     66         use++;
     67         a[use]=a[now];
     68         cnt[use]=cntl-1;
     69         lc(use)=lc(now); fa[lc(use)]=use;
     70         lc(now)=use; fa[use]=now;
     71         pushup(use);
     72     }
     73     a[now]+=cntl-1; cnt[now]-=cntl-1;
     74     if(cnt[now]>1){
     75         use++;
     76         a[use]=a[now]+1;
     77         cnt[use]=cnt[now]-1;
     78         rc(use)=rc(now); fa[rc(use)]=use;
     79         rc(now)=use; fa[use]=now;
     80         pushup(use);
     81     }
     82     cnt[now]=1;
     83     pushup(now);
     84     return now;
     85 }
     86 
     87 int main(){
     88 //    freopen("in.txt","r",stdin);
     89 //    freopen("out.txt","w",stdout);
     90     cin>>n>>m>>q;
     91     numuse=n*m;
     92     for(L i=1;i<=n;i++){
     93         rt[i]=++use;
     94         a[use]=(i-1)*m+1;
     95         cnt[use]=siz[use]=m-1;
     96         a[++use]=i*m; cnt[use]=1;
     97         ins(rty,i-1,use);
     98         splay(use,rty);
     99     }
    100     while(q--){
    101         int x,y; scanf("%d%d",&x,&y);
    102         int now=query(x,y),outy=0;L outnum;
    103         if(now){
    104             outnum=a[now];
    105             merge(lc(now),rc(now),rt[x]);
    106         }else outy=1;
    107         now=find(rty,x);
    108         splay(now,rty);
    109         if(outy) outnum=a[now];
    110         merge(lc(now),rc(now),rty);
    111         lc(now)=rc(now)=0;
    112         if(outy==0){
    113             ins(rt[x],m-1,now); 
    114             splay(now,rt[x]);
    115         }
    116         a[++use]=outnum; cnt[use]=1;
    117         ins(rty,n-1,use); splay(use,rty);
    118         printf("%lld
    ",outnum);
    119     }
    120 }
  • 相关阅读:
    VOC2012数据集
    flask 图像接口测试
    PyQt5 学习指南
    超分辨中的注意力机制:Attention in Super Resolution
    OpenCV:图像增亮与直方图均衡
    SOA 架构与微服务架构的区别
    Docker 部署 vue 项目
    element ui 中的 resetFields() 报错'resetFields' of undefined
    Mybatis分页方法
    Serializable的作用
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9711228.html
Copyright © 2011-2022 走看看