zoukankan      html  css  js  c++  java
  • bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1807  Solved: 772
    [Submit][Status][Discuss]

    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
    1.查询k在区间内的排名
    2.查询区间内排名为k的值
    3.修改某一位值上的数值
    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    Input

    第一行两个数 n,m 表示长度为n的有序序列和m个操作
    第二行有n个数,表示有序序列
    下面有m行,opt表示操作标号
    若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    Output

    对于操作1,2,4,5各输出一行,表示查询结果

    Sample Input

    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5

    Sample Output

    2
    4
    3
    4
    9

    HINT

    1.n和m的数据范围:n,m<=50000


    2.序列中每个数的数据范围:[0,1e8]


    3.虽然原题没有,但事实上5操作的k可能为负数

    【思路】

           线段树套名次树

           名次树上的各个操作和普通平衡树大致一样。

           一棵线段树,每一个节点为一棵Treap,各操作如下:

           操作1 -- 找出[l,r]内k的rank,得到比k小的数量s,则答案为s+1,在区间内统计比k小的数量即可。

           操作2 – 找出[l,r]内rank为k的数,二分查找该数M,通过操作1可以得到数M的rank,根据k与rank调整区间。

           操作3 – 修改pos上的数为k,在线段树上递归到位置pos,修改路径上的每一棵Treap,对应一次remove与一次insert。

           操作4 – 找出[l,r]内k的前驱,在区间每一棵包含区间的Treap上进行Treap中查找前驱的操作,更新ans。

           操作5 – 同理4

    【代码】

      1 #include<cstdio>
      2 #include<ctime>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<iostream>
      6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      7 using namespace std;
      8 
      9 const int N = 5*1e5+10;
     10 const int INF = 1e8;
     11 
     12 int n,m,val[N],tmp;
     13 //RANK TREE
     14 struct Node {
     15     Node* ch[2];
     16     int v,r,s,w;
     17     Node(int x):v(x) {ch[0]=ch[1]=NULL; s=w=1; r=rand();}
     18     void maintain() {
     19         s=w;
     20         if(ch[0]!=NULL) s+=ch[0]->s;
     21         if(ch[1]!=NULL) s+=ch[1]->s;
     22     }
     23     int cmp(int x) {
     24         if(x==v) return -1; else return x<v? 0:1;
     25     }
     26 };
     27 void rotate(Node* &o,int d) {
     28     Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d],k->ch[d]=o;
     29     o->maintain(),k->maintain(); o=k;
     30 }
     31 void insert(Node* &o,int x) {
     32     if(o==NULL) o=new Node(x);
     33     else {
     34         int d=o->cmp(x);
     35         if(d==-1) { o->w++; o->maintain(); return; }
     36         insert(o->ch[d],x);
     37         if(o->ch[d]->r > o->r) rotate(o,d^1);
     38     }
     39     o->maintain();
     40 }
     41 void remove(Node* &o,int x) {
     42     if(o==NULL) return;
     43     int d=o->cmp(x);
     44     if(d==-1) {
     45         Node* u=o;
     46         if(o->w>1) { o->w--;o->maintain();return; }
     47         if(o->ch[0]!=NULL&&o->ch[1]!=NULL) {
     48             int d2=o->ch[0]->r>o->ch[1]->r? 1:0;
     49             rotate(o,d2),remove(o->ch[d2],x);
     50         }
     51         else {
     52             if(o->ch[0]!=NULL) o=o->ch[0]; else o=o->ch[1];
     53             delete u;
     54         }
     55     } else remove(o->ch[d],x);
     56     if(o!=NULL) o->maintain();
     57 }
     58 void rank(Node* o,int x) {
     59     if(o==NULL) return ;
     60     int d=o->cmp(x),s=o->ch[0]==NULL? 0:o->ch[0]->s;
     61     if(d==-1) { tmp+=s; return ; }
     62     else if(d==0) rank(o->ch[0],x);
     63     else { tmp+=s+o->w; rank(o->ch[1],x); }
     64 }
     65 void before(Node* o,int x) {
     66     if(o==NULL) return ;
     67     if(o->v<x) { tmp=max(tmp,o->v); before(o->ch[1],x); }
     68     else before(o->ch[0],x);
     69 }
     70 void after(Node* o,int x) {
     71     if(o==NULL) return ;
     72     if(o->v>x) { tmp=min(tmp,o->v); after(o->ch[0],x); }
     73     else after(o->ch[1],x);
     74 }
     75 //SEGMENT TREE 2D
     76 Node* root[N>>1];
     77 void build(int u,int L,int R,int r,int x) {
     78     insert(root[u],x);
     79     if(L==R) return ;
     80     int M=(L+R)>>1;
     81     if(r<=M) build(u<<1,L,M,r,x);
     82     else build(u<<1|1,M+1,R,r,x);
     83 }
     84 void getrank(int u,int L,int R,int l,int r,int x) {
     85     if(l==L && r==R) { rank(root[u],x); return ; }
     86     int M=(L+R)>>1;
     87     if(r<=M) getrank(u<<1,L,M,l,r,x);
     88     else if(M<l) getrank(u<<1|1,M+1,R,l,r,x);
     89     else {
     90         getrank(u<<1,L,M,l,M,x);
     91         getrank(u<<1|1,M+1,R,M+1,r,x);
     92     }
     93 }
     94 void getindex(int x,int y,int k) {
     95     int num,L=0,R=INF,M;
     96     while(L<=R) {
     97         int M=(L+R)>>1;
     98         tmp=1;
     99         getrank(1,1,n,x,y,M);
    100         if(tmp<=k) L=M+1,num=M;
    101         else R=M-1;
    102     }
    103     printf("%d
    ",num);
    104 }
    105 void change(int u,int L,int R,int r,int x,int y) {
    106     remove(root[u],x),insert(root[u],y);
    107     if(L==R) return ;
    108     int M=(L+R)>>1;
    109     if(r<=M) change(u<<1,L,M,r,x,y);
    110     else change(u<<1|1,M+1,R,r,x,y);
    111 }
    112 void getbefore(int u,int L,int R,int l,int r,int x) {
    113     if(l==L && R==r) { before(root[u],x);return ;}
    114     int M=(L+R)>>1;
    115     if(r<=M) getbefore(u<<1,L,M,l,r,x);
    116     else if(l>M) getbefore(u<<1|1,M+1,R,l,r,x);
    117     else {
    118         getbefore(u<<1,L,M,l,M,x);
    119         getbefore(u<<1|1,M+1,R,M+1,r,x);
    120     }
    121 }
    122 void getafter(int u,int L,int R,int l,int r,int x) {
    123     if(l==L && R==r) { after(root[u],x); return ;}
    124     int M=(L+R)>>1;
    125     if(r<=M) getafter(u<<1,L,M,l,r,x);
    126     else if(l>M) getafter(u<<1|1,M+1,R,l,r,x);
    127     else {
    128         getafter(u<<1,L,M,l,M,x);
    129         getafter(u<<1|1,M+1,R,M+1,r,x);
    130     }
    131 }
    132 void read(int& x) {
    133     char c=getchar(); int f=1; x=0;
    134     while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
    135     while(isdigit(c)) x=x*10+c-'0',c=getchar();
    136     x*=f;
    137 }
    138 void trav(Node* o) {
    139     if(o==NULL) return ;
    140     FOR(i,1,o->w) cout<<o->v<<" ";
    141     trav(o->ch[0]),trav(o->ch[1]);
    142 }
    143 int main() {
    144     //freopen("in.in","r",stdin);
    145     //freopen("out.out","w",stdout);
    146     read(n),read(m);
    147     FOR(i,1,n) read(val[i]),build(1,1,n,i,val[i]);
    148     int op,a,b,c;
    149     while(m--) {
    150         read(op),read(a),read(b);
    151         switch(op) {
    152             case 1:
    153                 read(c); tmp=1; getrank(1,1,n,a,b,c);
    154                 printf("%d
    ",tmp);
    155                 break;
    156             case 2:
    157                 read(c); getindex(a,b,c);
    158                 break;
    159             case 3:
    160                 change(1,1,n,a,val[a],b); val[a]=b;
    161                 break;
    162             case 4:
    163                 read(c); tmp=0; getbefore(1,1,n,a,b,c);
    164                 printf("%d
    ",tmp);
    165                 break;
    166             case 5:
    167                 read(c); tmp=INF; getafter(1,1,n,a,b,c);
    168                 printf("%d
    ",tmp);
    169                 break;
    170         }
    171     }
    172     return 0;
    173 }
  • 相关阅读:
    sharepoint2013保存当前输入的列表
    网站模板的下载和使用
    sharepoint获取是否为输入域用户SharePoint PeopleEditor 控件的使用
    sharepoint指定的人可以看到列表项
    js隐藏显示div
    如何为同一IE浏览器中打开多个页面
    CDC相关知识点总结
    find 命令使用总结
    find 命令search使用
    verilog behavioral modeling --loop statement
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5194610.html
Copyright © 2011-2022 走看看