zoukankan      html  css  js  c++  java
  • [SCOI2014]方伯伯的OJ

    看到这道题的第一想法就是要用FHQ treap 过了这道题...于是至今尚未成功(华丽的 T 掉了 (╯‵□′)╯︵┻━┻ )。于是附个地址。

    然后水一波博客。

    题意简介

    emmmm...方伯伯脑抽做了个 oj ,然后想要在对 oj 上的 1~n 编号的用户乱来(并且还对他的乱来操作进行了加密)。你需要维护一棵平衡树完成方伯伯的一波操作

    你的平衡树需要支持这些操作: 1. 修改编号; 2. 把一个人放到树的最左边; 3. 把一个人放到树的最右边;4.输出一个排名对应的编号。

    题目分析

    然后这道题非常坑,要用 map 记录每个节点对应区间右端点的对应节点编号 (听起来很绕,其实就是: 设某节点对应区间右端点为 R , 该节点编号为 p , 那么我们用的map 的 first key 就是 R ,second key 是 p),然后用找某个编号所在的节点用 lower_bound 就好了(才知道map是可以 lower bound 的,并且是以第一关键字作比较的)。我记得有看到用另一种利用 map 的方法,那好像是 普通 treap (splay应该也能用啊)的,而且节点维护的区间也有点混乱...就是这个

    Splay 做法

      1 //by Judge
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<map>
      5 using namespace std;
      6 const int M=5e5+111;
      7 //#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
      8 char buf[1<<21],*p1=buf,*p2=buf;
      9 inline int read(){
     10     int x=0,f=1; char c=getchar();
     11     for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
     12     for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
     13 }
     14 char sr[1<<21],z[20];int C=-1,Z;
     15 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
     16 inline void print(int x){
     17     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
     18     while(z[++Z]=x%10+48,x/=10);
     19     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
     20 }
     21 int n,m,cnt,ans,root;
     22 map<int,int> mp;
     23 struct Node{
     24     int l,r,siz,fa,ch[2];
     25 }t[M];
     26 inline int newnode(int x,int y){ int u=++cnt; t[u].siz=y-x+1,t[u].l=x,t[u].r=y; return u; }
     27 inline void pushup(int x){ t[x].siz=t[t[x].ch[0]].siz+t[t[x].ch[1]].siz+t[x].r-t[x].l+1; }
     28 inline void rotate(int x){
     29     int y=t[x].fa,z=t[y].fa,sn=t[y].ch[1]==x;
     30     t[x].fa=z; if(z) t[z].ch[t[z].ch[1]==y]=x;
     31     t[y].ch[sn]=t[x].ch[!sn],t[t[y].ch[sn]].fa=y;
     32     t[y].fa=x,t[x].ch[!sn]=y,pushup(y);
     33 }
     34 inline void splay(int x,int to){
     35     while(t[x].fa^to){
     36         int y=t[x].fa,z=t[y].fa;
     37         if(z!=to) rotate((t[z].ch[0]==y)^(t[y].ch[0]==x)?x:y);
     38         rotate(x);
     39     } pushup(x); if(!to) root=x;
     40 }
     41 inline int query(int x){ splay(x,0); return t[x].siz-t[t[x].ch[1]].siz; }
     42 inline int get_id(int k){  //查询排名为 k 的人的编号
     43     int now=root;
     44     while(k){ 
     45         int sum=t[t[now].ch[0]].siz+t[now].r-t[now].l+1;
     46         if(t[t[now].ch[0]].siz<k && k<=sum){
     47             k-=t[t[now].ch[0]].siz; break;
     48         } else if(sum<k) k-=sum,now=t[now].ch[1];
     49         else now=t[now].ch[0];
     50     } return t[now].l+k-1;
     51 }
     52 inline void erase(int x){  //删除节点信息
     53     int pre=t[x].ch[0],nxt=t[x].ch[1];
     54     while(t[pre].ch[1]) pre=t[pre].ch[1];
     55     while(t[nxt].ch[0]) nxt=t[nxt].ch[0];
     56     if(!pre && !nxt) return (void)(root=0);
     57     if(!pre) splay(nxt,root),t[root=nxt].fa=0;
     58     else if(!nxt) splay(pre,root),t[root=pre].fa=0;
     59     else splay(pre,0),splay(nxt,pre),t[nxt].ch[0]=0,pushup(nxt),pushup(pre);
     60     t[x].ch[0]=t[x].ch[1]=0,t[x].siz=1;  //不知道为什么这里不写会 T (懒得想咯应该是编号改完可能会改回来的问题吧)
     61 }
     62 inline void push_front(int x){ //插头
     63     if(!root) return (void)(root=x); int fa=root;
     64     while(t[fa].ch[0]) ++t[fa].siz,fa=t[fa].ch[0];
     65     ++t[fa].siz,t[fa].ch[0]=x,t[x].fa=fa,splay(x,0);
     66 }
     67 inline void push_back(int x){  //插尾
     68     if(!root) return (void)(root=x); int fa=root;
     69     while(t[fa].ch[1]) ++t[fa].siz,fa=t[fa].ch[1];
     70     ++t[fa].siz,t[fa].ch[1]=x,t[x].fa=fa,splay(x,0);
     71 }
     72 inline void split(int x,int id){ //拆出节点
     73     int L=t[x].l,R=t[x].r,ls,rs;
     74     if(L==R) return ; //不用拆
     75     if(L==id){  //最左端
     76         mp[R]=rs=++cnt,mp[id]=x;
     77         t[rs].ch[1]=t[x].ch[1];
     78         t[t[rs].ch[1]].fa=rs;
     79         t[x].ch[1]=rs,t[rs].fa=x;
     80         t[rs].l=L+1,t[rs].r=R,t[x].r=L;
     81         pushup(rs),pushup(x);
     82     } else if(R==id){ //最右端
     83         mp[R-1]=ls=++cnt,mp[id]=x;
     84         t[ls].ch[0]=t[x].ch[0];
     85         t[t[ls].ch[0]].fa=ls;
     86         t[x].ch[0]=ls,t[ls].fa=x;
     87         t[ls].l=L,t[ls].r=R-1,t[x].l=R;
     88         pushup(ls),pushup(x);
     89     } else{  //在中间
     90         mp[id]=x,mp[id-1]=ls=++cnt,mp[R]=rs=++cnt;
     91         t[ls].ch[0]=t[x].ch[0],t[rs].ch[1]=t[x].ch[1];
     92         t[t[ls].ch[0]].fa=ls,t[t[rs].ch[1]].fa=rs;
     93         t[x].ch[0]=ls,t[x].ch[1]=rs,t[ls].fa=t[rs].fa=x;
     94         t[x].l=t[x].r=id,t[ls].l=L,t[ls].r=id-1,t[rs].l=id+1,t[rs].r=R;
     95         pushup(ls),pushup(rs),pushup(x);
     96     }
     97 }
     98 signed main() {
     99     n=read(),m=read(),
    100     mp[n]=root=newnode(1,n);
    101     for(int x,y,pos,opt;m;--m){
    102         opt=read();
    103         switch(opt){
    104             case 1:
    105                 x=read()-ans,y=read()-ans;
    106                 pos=mp.lower_bound(x)->second; //map 里面找节点编号
    107                 split(pos,x),ans=query(pos); //拆出节点查排名
    108                 t[pos].l=t[pos].r=y,mp[y]=pos; //修改信息输答案
    109                 print(ans); break;
    110             case 2:
    111                 x=read()-ans, pos=mp.lower_bound(x)->second;
    112                 split(pos,x),ans=query(pos),erase(pos); //拆除节点再删除
    113                 push_front(pos),print(ans); break; //节点重新加入树
    114             case 3:
    115                 x=read()-ans, pos=mp.lower_bound(x)->second;
    116                 split(pos,x),ans=query(pos),erase(pos);
    117                 push_back(pos),print(ans); break;
    118             case 4:
    119                 x=read()-ans,ans=get_id(x),print(ans); break; //询问编号直输出
    120         }
    121     } Ot(); return 0;
    122 }

    FHQ treap

  • 相关阅读:
    ant 软件包不存在报错
    在 Internet Explorer 中使用 Windows 窗体控件
    智能客户端
    Back to the Future with Smart Clients
    "Automation 服务器不能创建对象" 的解决方案
    Top 10 Reasons for Developers to Create Smart Clients
    Updater Application Block for .NET
    Smart Client Application Model and the .NET Framework 1.1
    Security and Versioning Models in the Windows Forms Engine Help You Create and Deploy Smart Clients
    智能客户端技术总结(二)
  • 原文地址:https://www.cnblogs.com/Judge/p/9538306.html
Copyright © 2011-2022 走看看