zoukankan      html  css  js  c++  java
  • 主席树初探--BZOJ1901: Zju2112 Dynamic Rankings

    n<=10000的序列做m<=10000个操作:单点修改,查区间第k小。

    所谓的主席树也就是一个值域线段树嘛。。不过在这里还是%%fotile

    需要做一个区间查询,由于查第k小,需要一些能够支持数值操作的东西,那就选择值域线段树,线段树上每个区间[L,R]表示的是值在L~R的数的相关信息,比如这里的“有多少个”。

    不过呢这样的线段树没法维护区间下标怎么求区间信息啊,那就BIT套线段树,BIT上每个点表示一段区间(lowbit)的数值之和。为了空间,先离散化再动态开点效果拔群。

    然后单点修改就该logn棵线段树,区间查询[L,R]就把R和L-1两个前缀的信息来相减。

    这里第一次写树套树,见识了一种好操作!因为要同时操作很多棵线段树并且要在里面走来走去,就开一些指针一起走。那怎么知道谁要走呢?每次要区间查询时先init一下,把设计的线段树标记出来。由于两个前缀相减可能会有一些树标记到两次,那在前缀相减完之后这些标记两次的相当于不用算了,所以就把他们标记清除即可。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stdlib.h>
     5 //#include<iostream>
     6 using namespace std;
     7 
     8 int n,m;
     9 #define maxn 20011
    10 #define maxm 4000011
    11 
    12 struct SMT
    13 {
    14     struct Node
    15     {
    16         int son[2];
    17         int l,r;
    18         int cnt;
    19     }a[maxm];
    20     int size,n;
    21     void clear(int m) {n=m;size=0;a[0].cnt=0;}
    22     void up(int x) {a[x].cnt=a[a[x].son[0]].cnt+a[a[x].son[1]].cnt;}
    23     void insert(int &x,int L,int R,int num)
    24     {
    25         if (!x) {x=++size;a[x].l=L;a[x].r=R;a[x].cnt=1;}
    26         else a[x].cnt++;
    27         if (L==R) return;
    28         const int mid=(L+R)>>1;
    29         if (num<=mid) insert(a[x].son[0],L,mid,num);
    30         else insert(a[x].son[1],mid+1,R,num);
    31     }
    32     void insert(int &x,int num) {insert(x,1,n,num);}
    33     void Delete(int &x,int L,int R,int num)
    34     {
    35         a[x].cnt--;
    36         if (!a[x].cnt) {x=0;return;}
    37         if (L==R) return;
    38         const int mid=(L+R)>>1;
    39         if (num<=mid) Delete(a[x].son[0],L,mid,num);
    40         else Delete(a[x].son[1],mid+1,R,num);
    41     }
    42     void Delete(int &x,int num) {Delete(x,1,n,num);}
    43 }smt;
    44 struct BIT
    45 {
    46     int a[maxn],t[maxn],n;
    47     int vis[maxn];
    48     void clear(int m) {n=m;memset(a,0,sizeof(a));memset(vis,0,sizeof(vis));}
    49     void add(int x,int num) {for (;x<=n;x+=x&-x) smt.insert(a[x],num);}
    50     void minus(int x,int num) {for (;x<=n;x+=x&-x) smt.Delete(a[x],num);}
    51     void init(int x,int Time)
    52     {for (;x;x-=x&-x) if (vis[x]!=Time) vis[x]=Time,t[x]=a[x];else vis[x]=0;}
    53     int query(int x,int Time)
    54     {int ans=0;for (;x;x-=x&-x) if (vis[x]==Time) ans+=smt.a[smt.a[t[x]].son[0]].cnt;return ans;}
    55     void turn(int x,int Time,int dir) {for (;x;x-=x&-x) if (vis[x]==Time) t[x]=smt.a[t[x]].son[dir];}
    56 }t;
    57 
    58 struct Doo
    59 {
    60     bool type;int x,y,z;
    61 }doo[maxn];
    62 int lisan[maxn],a[maxn],li=0;
    63 int main()
    64 {
    65     scanf("%d%d",&n,&m);
    66     for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisan[++li]=a[i];
    67     for (int i=1;i<=m;i++)
    68     {
    69         char c=' ';while (c!='Q' && c!='C') c=getchar();
    70         if ((doo[i].type=(c=='Q'))) scanf("%d%d%d",&doo[i].x,&doo[i].y,&doo[i].z);
    71         else scanf("%d%d",&doo[i].x,&doo[i].y),lisan[++li]=doo[i].y;
    72     }
    73     sort(lisan+1,lisan+1+li);li=unique(lisan+1,lisan+1+li)-lisan-1;
    74     for (int i=1;i<=n;i++) a[i]=lower_bound(lisan+1,lisan+1+li,a[i])-lisan;
    75     for (int i=1;i<=m;i++) if (!doo[i].type) doo[i].y=lower_bound(lisan+1,lisan+1+li,doo[i].y)-lisan;
    76     
    77     t.clear(n);smt.clear(li);
    78     for (int i=1;i<=n;i++) t.add(i,a[i]);
    79     for (int i=1;i<=m;i++)
    80     {
    81         if (doo[i].type)
    82         {
    83             int x=doo[i].x-1,y=doo[i].y,z=doo[i].z,l=1,r=li,tmp;
    84             t.init(y,i);t.init(x,i);
    85             while (l<r)
    86             {
    87                 if ((tmp=t.query(y,i)-t.query(x,i))>=z) r=(l+r)>>1,t.turn(y,i,0),t.turn(x,i,0);
    88                 else l=((l+r)>>1)+1,z-=tmp,t.turn(y,i,1),t.turn(x,i,1);
    89             }
    90             printf("%d
    ",lisan[l]);
    91         }
    92         else
    93         {
    94             t.minus(doo[i].x,a[doo[i].x]);
    95             t.add(doo[i].x,(a[doo[i].x]=doo[i].y));
    96         }
    97     }
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    2019-2020-3 20175324 王陈峤宇《网络对抗技术》Exp3 免杀原理与实践
    2019-2020-2 20175324 王陈峤宇《网络对抗技术》Exp2 后门原理与实践
    2019-2020-3 20175324王陈峤宇《网络对抗技术》Exp1 PC平台逆向破解
    2019-2020- 20175324王陈峤宇 Exp0 环境搭建-KALI LINUX安装
    2019-2020-2 20175330杨璟旭《网络对抗技术》Exp9 Web安全基础
    2019-2020-2 网络对抗技术 20175330 Exp8 Web基础
    2019-2020-2 网络对抗技术 20175330 Exp7 网络欺诈防范
    2019-2020-2 网络对抗技术 20175330杨璟旭 Exp6 MSF基础应用
    2019-2020-2 20175330杨璟旭《网络对抗技术》Exp5信息搜集与漏洞扫描
    2019-2020-2 20175330杨璟旭《网络对抗技术》Exp4 恶意代码分析
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7921154.html
Copyright © 2011-2022 走看看