zoukankan      html  css  js  c++  java
  • splay(水题)

    昨天讲了splay,然而一脸蒙蔽,今天写了个模版

    洛谷p3369

    没错,标准模版

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入xxx数
    2. 删除xxx数(若有多个相同的数,因只删除一个)
    3. 查询xxx数的排名(排名定义为比当前数小的数的个数+1+1+1。若有多个相同的数,因输出最小的排名)
    4. 查询排名为xxx的数
    5. xxx的前驱(前驱定义为小于xxx,且最大的数)
    6. xxx的后继(后继定义为大于xxx,且最小的数)

    输入输出格式

    输入格式:

    第一行为nnn,表示操作的个数,下面nnn行每行有两个数optoptopt和xxx,optoptopt表示操作的序号( 1≤opt≤6 1 leq opt leq 6 1opt6 )

    输出格式:

    对于操作3,4,5,63,4,5,63,4,5,6每行输出一个数,表示对应答案

    输入输出样例

    输入样例#1: 复制
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    输出样例#1: 复制
    106465
    84185
    492737

    说明

    时空限制:1000ms,128M

    1.n的数据范围: n≤100000 n leq 100000 n100000

    2.每个数的数据范围: [−107,107][-{10}^7, {10}^7][107,107]

    来源:Tyvj1728 原名:普通平衡树

    在此鸣谢

    细节决定一切,模版要慢慢打

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int inf=1e7+10;
      4 const int maxn=200005;
      5 int par[maxn],cnt[maxn],ch[maxn][2],size[maxn],val[maxn],ncnt=0,n,root;
      6 void pushup(int x){
      7     size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
      8 }
      9 bool chk(int x){
     10     return ch[par[x]][1]==x;
     11 }
     12 void rotate(int x){
     13     int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
     14     ch[y][k]=w;
     15     par[w]=y;
     16     ch[z][chk(y)]=x;
     17     par[x]=z;
     18     ch[x][k^1]=y;
     19     par[y]=x;
     20     pushup(y);pushup(x);
     21 }
     22 void splay(int x,int goal=0){
     23     while(par[x]!=goal){
     24         int y=par[x],z=par[y];
     25         if(z!=goal){
     26             if(chk(x)==chk(y)) rotate(y);
     27             else rotate(x);
     28         }
     29         rotate(x);
     30     }
     31     if(!goal) root=x;
     32 }
     33 void insert(int x){
     34     int cur=root,fa=0;
     35     while(val[cur]!=x&&cur){
     36         fa=cur;
     37         cur=ch[cur][x>val[cur]];
     38     }
     39     if(cur){
     40         cnt[cur]++;
     41     }
     42     else {
     43         cur=++ncnt;val[cur]=x;
     44         if(fa)
     45         ch[fa][x>val[fa]]=cur;
     46         ch[cur][0]=ch[cur][1]=0;
     47         size[cur]=1;cnt[cur]=1;
     48         par[cur]=fa;
     49     }
     50     splay(cur);
     51 }
     52 void find(int x){
     53     int cur=root;
     54     while(val[cur]!=x&&ch[cur][x>val[cur]]) cur=ch[cur][x>val[cur]];
     55     splay(cur);
     56 }
     57 int kth(int k){
     58     int cur=root;
     59     while(1){
     60         if(size[ch[cur][0]]>=k) cur=ch[cur][0];
     61         else if(size[ch[cur][0]]+cnt[cur]>=k) return cur;
     62         else {
     63             k-=size[ch[cur][0]]+cnt[cur];
     64             cur=ch[cur][1];
     65         }
     66     }
     67 }
     68 int pre(int x){
     69     find(x);
     70     int cur=root;
     71     if(val[cur]<x) return cur;
     72     cur=ch[cur][0];
     73     while(ch[cur][1]) cur=ch[cur][1];
     74     return cur;
     75 }
     76 int suc(int x){
     77     find(x);
     78     int cur=root;
     79     if(val[cur]>x) return cur;
     80     cur=ch[cur][1];
     81     while(ch[cur][0]) cur=ch[cur][0];
     82     return cur;
     83 }
     84 void remove(int x){
     85     int last=pre(x),next=suc(x);
     86     splay(last);
     87     splay(next,last);
     88     if(cnt[ch[next][0]]==1){
     89         ch[next][0]=0;
     90     }
     91     else {
     92         cnt[ch[next][0]]--;
     93         splay(ch[next][0]);
     94     }
     95 }
     96 int main(){
     97     scanf("%d",&n);
     98     insert(inf);insert(-inf);
     99     for(int i=1;i<=n;i++){
    100         int opt,x;
    101         scanf("%d%d",&opt,&x);
    102         switch(opt){
    103             case 1:
    104                 insert(x);
    105                 break;
    106             case 2:
    107                 remove(x);
    108                 break;
    109             case 3:
    110                 find(x);
    111                 printf("%d
    ",size[ch[root][0]]);
    112                 break;
    113             case 4:
    114                 printf("%d
    ",val[kth(x+1)]);
    115                 break;
    116             case 5:
    117                 printf("%d
    ",val[pre(x)]);
    118                 break;
    119             case 6:
    120                 printf("%d
    ",val[suc(x)]);
    121                 break;
    122         }
    123     }
    124     return 0;
    125 }
    View Code

    还有一道要转化的题

    洛谷p1503

    鬼子进村

    题目背景

    小卡正在新家的客厅中看电视。电视里正在播放放了千八百次依旧重播的《亮剑》,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战。

    题目描述

    描述 县城里有n个用地道相连的房子,第i个只与第i-1和第i+1个相连。这是有m个消息依次传来

    1、消息为D x:鬼子将x号房子摧毁了,地道被堵上。

    2、消息为R :村民们将鬼子上一个摧毁的房子修复了。

    3、消息为Q x:有一名士兵被围堵在x号房子中。

    李云龙收到信息很紧张,他想知道每一个被围堵的士兵能够到达的房子有几个。

    输入输出格式

    输入格式:

    第一行2个整数n,m(n,m<=50000)。

    接下来m行,有如题目所说的三种信息共m条。

    输出格式:

    对于每一个被围堵的士兵,输出该士兵能够到达的房子数。

    输入输出样例

    输入样例#1: 复制
    7 9
    D 3
    D 6
    D 5
    Q 4
    Q 5
    R
    Q 4
    R
    Q 4
    
    输出样例#1: 复制
    1
    0
    2
    4
    

    说明

    若士兵被围堵在摧毁了的房子中,那只能等死了。。。。。。

    当然这题暴力可过,但是splay也还行

    不能把没有摧毁的房子插进去,而是把被摧毁的插进去,这样操作就简单了,因为还有修复,所以要开个栈来保存被摧毁的房子编号

    计算房子数的话就先查看当前节点是否在树中,在的话直接输0,否则找前驱与后驱,注意相减后还要减一

    初始化时插入0和n+1

    还有可能会读入奇奇怪怪的字符,所以读字符时要处理下

      1 #include<stack>
      2 #include<cstdio>
      3 using namespace std;
      4 const int maxn = 5e4+5;
      5 inline int read(){
      6     int x=0,f=1;char ch=getchar();
      7     while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}
      8     while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
      9     return x*f;
     10 }
     11 void getc(char &c){//处理字符,第一次没这样做直接爆零(只能说数据坑
     12     c=getchar();
     13     while(c!='D'&&c!='R'&&c!='Q'){
     14         c=getchar();
     15     }
     16 }
     17 stack<int> s;
     18 int ch[maxn][2],par[maxn],size[maxn],val[maxn],cnt[maxn],root,n,m,ncnt;
     19 
     20 void pushup(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];}
     21 
     22 int chk(int x){return x==ch[par[x]][1];}
     23 
     24 void rotate(int x){
     25     int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
     26     ch[y][k]=w;
     27     par[w]=y;
     28     ch[z][chk(y)]=x;
     29     par[x]=z;
     30     ch[x][k^1]=y;
     31     par[y]=x;
     32     pushup(y);
     33     pushup(x);
     34 }
     35 
     36 void splay(int x,int goal=0){
     37     while(par[x]!=goal){
     38         int y=par[x],z=par[y];
     39         if(z!=goal){
     40             if(chk(y)==chk(x)) rotate(y);
     41             else rotate(x);
     42         }
     43         rotate(x);
     44     }
     45     if(!goal) root=x;
     46 }
     47 
     48 void find(int x){
     49     int cur=root;
     50     while(val[cur]!=x&&ch[cur][x>val[cur]]) cur=ch[cur][x>val[cur]];
     51     splay(cur);
     52 }
     53 
     54 int pre(int x){
     55     find(x);
     56     if(val[root]<x) return root;
     57     int cur=ch[root][0];
     58     while(ch[cur][1]) cur=ch[cur][1];
     59     return cur;
     60 }
     61 
     62 int suc(int x){
     63     find(x);
     64     if(val[root]>x) return root;
     65     int cur=ch[root][1];
     66     while(ch[cur][0]) cur=ch[cur][0];
     67     return cur;
     68 }
     69 
     70 void remove(int x){
     71     int last=pre(x),next=suc(x);
     72     splay(last);
     73     splay(next,last);
     74     ch[next][0]=0;
     75 }
     76 
     77 void insert(int x){
     78     int cur=root,fa=0;
     79     while(val[cur]!=x&&cur) fa=cur,cur=ch[cur][x>val[cur]];
     80     if(!cur){
     81         cur=++ncnt;val[cur]=x;
     82         if(fa)
     83         ch[fa][x>val[fa]]=cur;
     84         ch[cur][0]=ch[cur][1]=0;
     85         size[cur]=1;cnt[cur]=1;
     86         par[cur]=fa;
     87     }
     88     else cnt[cur]++;
     89     splay(cur);
     90 }
     91 
     92 int main(){
     93     n=read(),m=read();
     94     insert(0);
     95     insert(n+1);
     96     for(int i=1;i<=m;i++){
     97         char a;getc(a);
     98         if(a=='D'){
     99             int x=read();
    100             insert(x);
    101             s.push(x);
    102         }
    103         else if(a=='R'){
    104             remove(s.top());
    105             s.pop();
    106         }
    107         else if(a=='Q'){
    108             int x=read();
    109             find(x);
    110             if(val[root]==x) printf("0
    ");
    111             
    112             else {
    113                 int succ=suc(x);
    114                 int pree=pre(x);
    115                 printf("%d
    ",val[succ]-val[pree]-1);
    116             }
    117         }
    118     }
    119 }
    View Code

    先写了这两个题,慢慢来。。。。

  • 相关阅读:
    RDIFramework.NET开发实例━表约束条件权限的使用-WinForm
    RDIFramework.NET V2.8版本 ━ 开发实例之产品管理(WinForm)
    RDIFramework.NET ━ Web中打印的各种方案参考-欢迎补充
    RDIFramework.NET 框架兼容各种数据库类型事务使用范例参考
    【干货】再上数据分页控件 ━ 更加灵活,更加实用-提供源码
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本━新增岗位管理-Web部分
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本━新增岗位管理-WinForm部分
    RDIFramework.NET ━ .NET快速信息化系统开发框架 V2.8 版本发布
    Javascript中的apply与call详解
    Javascript定义类(class)的三种方法
  • 原文地址:https://www.cnblogs.com/plysc/p/10382765.html
Copyright © 2011-2022 走看看