• Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap


    1901: Zju2112 Dynamic Rankings

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 6471  Solved: 2697
    [Submit][Status][Discuss]

    Description

    给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。

    Input

    对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

    Output

     

    Sample Input

    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3

    Sample Output

    3
    6

    HINT

    20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

    Source

     区间线段树套Treap
    上次写了个树状数组套主席树,这次复习一下区间线段树套Treap。
    就是在询问时,去二分答案,然后判定小于等于二分的答案的个数是否有K个即可。
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MAXN 10010
      4 struct node
      5 {
      6     int left,right,val,size,rnd,count;
      7 }tree[MAXN*300];
      8 int tmp,SIZE,root[MAXN*300],a[MAXN];
      9 int read()
     10 {
     11     int s=0,fh=1;char ch=getchar();
     12     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     13     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     14     return s*fh;
     15 }
     16 void Update(int k){tree[k].size=tree[tree[k].left].size+tree[tree[k].right].size+tree[k].count;}
     17 void Lturn(int &k){int t=tree[k].right;tree[k].right=tree[t].left;tree[t].left=k;tree[t].size=tree[k].size;Update(k);k=t;}
     18 void Rturn(int &k){int t=tree[k].left;tree[k].left=tree[t].right;tree[t].right=k;tree[t].size=tree[k].size;Update(k);k=t;}
     19 void Insert(int &k,int x)
     20 {
     21     if(k==0)
     22     {
     23         SIZE++;k=SIZE;
     24         tree[k].val=x;tree[k].size=tree[k].count=1;tree[k].rnd=rand();
     25         return;
     26     }
     27     tree[k].size++;
     28     if(x==tree[k].val){tree[k].count++;return;}
     29     if(x<tree[k].val){Insert(tree[k].left,x);if(tree[tree[k].left].rnd<tree[k].rnd)Rturn(k);}
     30     else {Insert(tree[k].right,x);if(tree[tree[k].right].rnd<tree[k].rnd)Lturn(k);}
     31 }
     32 void Del(int &k,int x)
     33 {
     34     if(k==0)return;
     35     if(tree[k].val==x)
     36     {
     37         if(tree[k].count>1){tree[k].size--;tree[k].count--;return;}
     38         if(tree[k].left*tree[k].right==0)k=tree[k].left+tree[k].right;
     39         else if(tree[tree[k].left].rnd<tree[tree[k].right].rnd){Rturn(k);Del(k,x);}
     40         else {Lturn(k);Del(k,x);}
     41     }
     42     else if(x<tree[k].val){tree[k].size--;Del(tree[k].left,x);}
     43     else {tree[k].size--;Del(tree[k].right,x);}
     44 }
     45 void Find(int k,int x)
     46 {
     47     if(k==0)return;
     48     if(tree[k].val<=x){tmp+=(tree[tree[k].left].size+tree[k].count);Find(tree[k].right,x);}
     49     else Find(tree[k].left,x);
     50 }
     51 void Build(int k,int l,int r,int lr,int B)
     52 {
     53     Insert(root[k],B);
     54     if(l==r)return;
     55     int mid=(l+r)/2;
     56     if(lr<=mid)Build(k*2,l,mid,lr,B);
     57     else Build(k*2+1,mid+1,r,lr,B);
     58 }
     59 void Query(int k,int l,int r,int ql,int qr,int Q)
     60 {
     61     if(l==ql&&r==qr){Find(root[k],Q);return;}
     62     int mid=(l+r)/2;
     63     if(qr<=mid)Query(k*2,l,mid,ql,qr,Q);
     64     else if(ql>mid)Query(k*2+1,mid+1,r,ql,qr,Q);
     65     else {Query(k*2,l,mid,ql,mid,Q);Query(k*2+1,mid+1,r,mid+1,qr,Q);}
     66 }
     67 void Change(int k,int l,int r,int lr,int C1,int C2)
     68 {
     69     Del(root[k],C1);
     70     Insert(root[k],C2);
     71     if(l==r)return;
     72     int mid=(l+r)/2;
     73     if(lr<=mid)Change(k*2,l,mid,lr,C1,C2);
     74     else Change(k*2+1,mid+1,r,lr,C1,C2);
     75 }
     76 int main()
     77 {
     78     int n,m,i,l,r,k,L,R,mid,ii,ans;
     79     char zs;
     80     n=read();m=read();
     81     for(i=1;i<=n;i++)a[i]=read();
     82     for(i=1;i<=n;i++)Build(1,1,n,i,a[i]);
     83     for(i=1;i<=m;i++)
     84     {
     85         scanf("
    %c",&zs);
     86         if(zs=='Q')
     87         {
     88             l=read();r=read();k=read();
     89             L=0;R=1000000000;ans=0;
     90             while(L<=R)
     91             {
     92                 mid=(L+R)/2;
     93                 tmp=0;
     94                 Query(1,1,n,l,r,mid);
     95                 if(tmp<k)L=mid+1;
     96                 else {ans=mid;R=mid-1;}
     97                 //else {ans=mid;break;}
     98                 //if(tmp>=k)R=mid-1;
     99                 //else L=mid+1;
    100             }
    101             //printf("%d
    ",L);
    102             printf("%d
    ",ans);
    103         }
    104         else
    105         {
    106             ii=read();k=read();
    107             Change(1,1,n,ii,a[ii],k);
    108             a[ii]=k;
    109         }
    110     }
    111     fclose(stdin);
    112     fclose(stdout);
    113     return 0;
    114 }
  • 相关阅读:
    iOS 之 内存管理
    php的异步并行扩展swoole
    如何用php实现qq登陆网站
    php分页类
    php的分页代码
    一个小的投票系统
    php如何判断两个时间戳是一天
    PHP中出现Notice: Undefined index的三种解决办法
    vmvare如何安装xp虚拟机
    windows2003安装
  • 原文地址:https://www.cnblogs.com/Var123/p/5336478.html
Copyright © 2020-2023  润新知