• 【bzoj3196-二逼平衡树】线段树套平衡树


    http://acm.hust.edu.cn/vjudge/problem/42297

    【题目描述】

    写一种数据结构,来维护一个有序数列,其中需要提供以下操作:

    1.查询k在区间内的排名

    2.查询区间内排名为k的值

    3.修改某一位值上的数值

    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)

    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    【输入格式】

    第一行两个数 n,m( n,m <= 50000 )表示长度为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的前驱(没有前驱输出no

    opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]k的后继(没有后继输出no

    【输出格式】

    对于操作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、序列中每个数的数据范围:[0,1e8]

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

     

     

    这题我在bzoj上AC,在tvoj上最后两个点TLE(然而并不知道怎么优化)。

    昨天中午打了一个中午,晚上调了一个钟,今天早上又调了两个钟。。呵呵。。

    我的做法是在开一棵1~n的线段树t,每个节点(管理t[x].l~t[x].r)开一棵treap,把t[x].l~t[x].r的值全部放进去。为了防止找前驱后继的时候有问题,每棵treap上先放-Inf和Inf进去。

    1.表示查询k在区间[l,r]的排名:用线段树找到[l,r]所需要用到的线段树上的节点,开一个数组存起来,然后一个个区间查询比k小的数的个数。

    2.表示查询区间[l,r]内排名为k的数:mn和mx存下出现过的最小和最大的数是什么。二分一个数x,然后用1的方法看x的排名。

    这里注意一个问题:找的是排名<=k的最大的数。

    例如:1 2 3 3 3 5,查询3的排名是3,但是如果我们要找排名为4的数,答案依然是3。

    3.单点修改:顺着线段树走下去,中途所经过的点,都要在它那棵treap上del原来的数,ins新数

    4.找前驱:就在线段树上先找出所有要用到的点,再一个个进去找在这棵treap树上的前驱x,取最大值。

    5.找后继:同上。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 using namespace std;
      6 
      7 const int N=50010,TN=50000*16+100,Inf=(int)1e9;
      8 struct tr_node{
      9     int son[2],n,c,f,d;
     10 }c[2*TN];
     11 struct xd_node{
     12     int lc,rc,l,r,root;
     13 }t[2*2*N];
     14 int tl,cl,sl;
     15 int w[2*N],s[2*N];
     16 
     17 void updata(int x)
     18 {
     19     if(!x) return;
     20     int lc=c[x].son[0],rc=c[x].son[1];
     21     c[x].c=c[x].n+c[lc].c+c[rc].c;
     22 }
     23 
     24 void add(int d,int f)
     25 {
     26     cl++;
     27     c[cl].f=f;c[cl].d=d;
     28     c[cl].n=c[cl].c=1;
     29     c[cl].son[0]=c[cl].son[1]=0;
     30     if(d<c[f].d) c[f].son[0]=cl;
     31     else c[f].son[1]=cl;
     32     updata(f);//debug
     33 }
     34 
     35 int find_ip(int d,int id)
     36 {
     37     int x=t[id].root;
     38     while(c[x].d!=d)
     39     {
     40         if(d<c[x].d)
     41         {
     42             if(c[x].son[0]) x=c[x].son[0];
     43             else break;
     44         }
     45         else 
     46         {
     47             if(c[x].son[1]) x=c[x].son[1];
     48             else break;
     49         }
     50     }
     51     return x;
     52 }
     53 
     54 void rotate(int x)
     55 {
     56     int y=c[x].f,z=c[y].f,w,r,R;
     57     w=(c[y].son[0]==x) ? 1:0;
     58     
     59     r=c[x].son[w];R=y;
     60     c[R].son[1-w]=r;
     61     if(r) c[r].f=R;
     62     
     63     r=x;R=z;
     64     c[R].son[(c[z].son[0]==y) ? 0:1]=r;
     65     c[r].f=R;
     66     
     67     r=y;R=x;
     68     c[R].son[w]=r;
     69     c[r].f=R;
     70     
     71     updata(y);
     72     updata(x);
     73 }
     74 
     75 void splay(int x,int rt,int id)
     76 {
     77     while(c[x].f!=rt)
     78     {
     79         int y=c[x].f,z=c[y].f;
     80         if(z==rt) rotate(x);
     81         else
     82         {
     83             if((c[z].son[0]==y) == (c[y].son[0]==x)) rotate(y),rotate(x);
     84             else rotate(x),rotate(x);
     85         }
     86     }
     87     if(rt==0) t[id].root=x;
     88 }
     89 
     90 void ins(int d,int id)
     91 {
     92     int root=t[id].root;
     93     if(root==0) {add(d,0);t[id].root=cl;return;}
     94     int x=find_ip(d,id);
     95     if(c[x].d==d) c[x].n++;
     96     else add(d,x);
     97     updata(x);
     98     splay(x,0,id);
     99 }
    100 
    101 int build_xd_tree(int l,int r)
    102 {
    103     int x=++tl;
    104     t[x].l=l;t[x].r=r;
    105     t[x].lc=t[x].rc=0;
    106     t[x].root=0;
    107     if(l<r)
    108     {
    109         int mid=(l+r)>>1;
    110         t[x].lc=build_xd_tree(l,mid);
    111         t[x].rc=build_xd_tree(mid+1,r);
    112         ins(-Inf,x);ins(Inf,x);
    113         for(int i=l;i<=r;i++) ins(w[i],x);
    114     }
    115     else ins(-Inf,x),ins(Inf,x),ins(w[t[x].l],x);//l==r
    116     return x;
    117 }
    118 
    119 void find_xd_id(int x,int l,int r)
    120 {
    121     if(t[x].l==l && t[x].r==r) {s[++sl]=x;return;}
    122     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1;
    123     if(r<=mid) find_xd_id(lc,l,r);
    124     else if(l>mid) find_xd_id(rc,l,r);
    125     else  find_xd_id(lc,l,mid),find_xd_id(rc,mid+1,r);
    126 }
    127 
    128 int find_qq(int d,int id)
    129 {
    130     int x=find_ip(d,id);splay(x,0,id);//debug splay(x,0,id)
    131     if(c[x].d>=d && c[x].son[0])
    132     {
    133         x=c[x].son[0];
    134         while(c[x].son[1]) x=c[x].son[1];
    135     }
    136     if(c[x].d>=d) x=0;
    137     return x;
    138 }
    139 
    140 int find_hj(int d,int id)
    141 {
    142     int x=find_ip(d,id);splay(x,0,id);//debug
    143     if(c[x].d<=d && c[x].son[1])
    144     {
    145         x=c[x].son[1];
    146         while(c[x].son[0]) x=c[x].son[0];
    147     }
    148     if(c[x].d<=d) x=0;
    149     return x;
    150 }
    151 
    152 void del(int d,int id)
    153 {
    154     int x=find_ip(d,id);splay(x,0,id);
    155     if(c[x].n>=2) {c[x].n--;return;}
    156     int x0=find_qq(d,id);
    157     int x1=find_hj(d,id);
    158     splay(x0,0,id);
    159     splay(x1,x0,id);
    160     c[x1].son[0]=0;
    161     updata(x1);
    162 }
    163 
    164 void change(int x,int p,int d)
    165 {
    166     if(t[x].l==t[x].r) 
    167     {
    168         del(w[p],x);ins(d,x);
    169         return;
    170     }
    171     int lc=t[x].lc,rc=t[x].rc,mid=(t[x].l+t[x].r)>>1;
    172     if(p<=mid) change(lc,p,d);
    173     else change(rc,p,d);
    174     del(w[p],x);ins(d,x);
    175 }
    176 
    177 int find_rk(int d,int id)//the number of all that <d
    178 {
    179     int root=t[id].root;
    180     int x=find_qq(d,id);
    181     splay(x,0,id);
    182     return c[c[x].son[0]].c-1+c[x].n;
    183 }
    184 
    185 int opt1(int k,int l,int r)
    186 {
    187     int ans=0;
    188     sl=0;find_xd_id(1,l,r);
    189     for(int j=1;j<=sl;j++) 
    190         ans+=find_rk(k,s[j]);
    191     return ans+1;
    192 }
    193 
    194 int minn(int x,int y){return x<y ? x:y;}
    195 int maxx(int x,int y){return x>y ? x:y;}
    196 
    197 int find_rank(int k)
    198 {
    199     int ans=0;
    200     for(int i=1;i<=sl;i++) 
    201         ans+=find_rk(k,s[i]);
    202     return ans+1;
    203 }
    204 
    205 int main()
    206 {
    207     freopen("a.in","r",stdin);
    208     freopen("a.out","w",stdout);
    209     int n,m;
    210     scanf("%d%d",&n,&m);
    211     tl=0;cl=0;
    212     int mn=Inf,mx=-Inf;
    213     for(int i=1;i<=n;i++) 
    214     {
    215         scanf("%d",&w[i]);
    216         mn=minn(mn,w[i]);
    217         mx=maxx(mx,w[i]);
    218     }
    219     build_xd_tree(1,n);
    220     for(int i=1;i<=m;i++)
    221     {
    222         int k,l,r,pos,opt;
    223         scanf("%d",&opt);
    224         if(opt!=3) scanf("%d%d%d",&l,&r,&k);
    225         else scanf("%d%d",&pos,&k);
    226         if(opt==1) 
    227         {
    228             int ans=0;
    229                 sl=0;find_xd_id(1,l,r);
    230             printf("%d
    ",find_rank(k));
    231         }
    232         if(opt==2)
    233         {
    234             sl=0;find_xd_id(1,l,r);
    235             int ll=mn,rr=mx;
    236             while(ll!=rr)
    237             {
    238                 int mid=(ll+rr+1)>>1;
    239                 int now=find_rank(mid);
    240                 if(now<=k) ll=mid;//注意
    241                 else rr=mid-1;
    242             }
    243             printf("%d
    ",ll);
    244         }
    245         if(opt==3)
    246         {
    247             change(1,pos,k);
    248             w[pos]=k;
    249             mn=minn(mn,k);
    250             mx=maxx(mx,k);
    251         }
    252         if(opt==4)
    253         {
    254             int ans=-Inf;
    255             sl=0;find_xd_id(1,l,r);
    256             for(int j=1;j<=sl;j++) ans=maxx(ans,c[find_qq(k,s[j])].d);    
    257             if(ans!=-Inf) printf("%d
    ",ans);
    258             else printf("no
    ");
    259         }
    260         if(opt==5)
    261         {
    262             int ans=Inf;
    263             sl=0;find_xd_id(1,l,r);
    264             for(int j=1;j<=sl;j++) ans=minn(ans,c[find_hj(k,s[j])].d);
    265             if(ans!=Inf) printf("%d
    ",ans);
    266             else printf("no
    ");
    267         }
    268     }
    269     return 0;
    270 }
  • 相关阅读:
    poj 3273 Monthly Expense(贪心+二分)
    codeforces 235 div2 C Team
    ZOJ 3607 Lazier Salesgirl(贪心)
    poj 1185 炮兵阵地(三维状态压缩dP)
    poj 2411 Mondriaan's Dream(状态压缩dP)
    sdut 2819 比赛排名(边表 拓扑排序)
    hdu 1421 搬寝室(dp)
    hdu 1243 反恐训练营(dp 最大公共子序列变形)
    Codeforces Round #232 (Div. 2) B. On Corruption and Numbers
    hdu 1559 最大子矩阵 (简单dp)
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5755711.html
Copyright © 2020-2023  润新知