zoukankan      html  css  js  c++  java
  • bzoj1901

    1901: Zju2112 Dynamic Rankings

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 6640  Solved: 2762
    [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

     题解:区间第k大,加修改操作,就是动态主席树,用主席树套树状数组写,就慢慢地A了。
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<algorithm>
      6 #define maxn 200001
      7 #define maxnode 2200001
      8 using namespace std;
      9 int list[maxn],h[maxn];
     10 int rt[maxnode],lt[maxnode],root[maxnode],sum[maxnode];
     11 int L[maxn],R[maxn];
     12 int ed,st,tot,size,n,node,m;
     13 char ch;
     14 struct date{int l,r,val,k;
     15 }a[maxn];
     16 int read()
     17 {
     18     int x=0; char ch; bool bo=0;
     19     while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1;
     20     while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');
     21     if (bo==1) return -x; return x;
     22 }
     23 int lowbit(int k)
     24 {
     25     return (k&(-k));
     26 }
     27 void ins(int x,int &y,int l,int r,int val ,int kk)
     28 {
     29     y=++size;
     30     sum[y]=sum[x]+kk; int mid=(l+r)>>1; rt[y]=rt[x]; lt[y]=lt[x];
     31     if (l==r) return ;
     32     if (val<=mid) ins(lt[x],lt[y],l,mid,val,kk);
     33     else ins(rt[x],rt[y],mid+1,r,val,kk);
     34 }
     35 void build()
     36 {
     37     for (int i=1; i<=n; i++)
     38         for (int j=i; j<=n; j+=lowbit(j)) 
     39         ins(root[j],root[j],1,tot,h[i],1);
     40 }
     41 int query(int l,int r,int k)
     42 {
     43     if (l==r) return l;
     44     int mid=(l+r)>>1; int suml=0,sumr=0;
     45     for (int i=1; i<=st; i++) suml+=sum[lt[L[i]]];
     46     for (int i=1; i<=ed; i++) sumr+=sum[lt[R[i]]];
     47     if (sumr-suml>=k)
     48     {
     49         for (int i=1; i<=st; i++) L[i]=lt[L[i]];
     50         for (int i=1; i<=ed; i++) R[i]=lt[R[i]];
     51         return query(l,mid,k); 
     52     }
     53     else
     54     {
     55         for (int i=1; i<=st; i++) L[i]=rt[L[i]];
     56         for (int i=1; i<=ed; i++) R[i]=rt[R[i]];
     57         return query(mid+1,r,k-sumr+suml);
     58     }
     59 }
     60 void solve()
     61 {
     62     node=n;
     63     for (int i=1; i<=m; i++)
     64     {
     65         if (!a[i].k) 
     66         {
     67             st=ed=0;
     68             a[i].l--;
     69             for (int j=a[i].l; j>0; j-=lowbit(j)) L[++st]=root[j];
     70             for (int j=a[i].r; j>0; j-=lowbit(j)) R[++ed]=root[j];
     71             printf("%d
    ",list[query(1,tot,a[i].val)]); 
     72         }
     73         else
     74         {
     75             ++node; 
     76             int t=h[a[i].l];
     77             for (int j=a[i].l; j<=n; j+=lowbit(j)) ins(root[j],root[j],1,tot,t,-1);
     78             h[a[i].l]=t=h[node];
     79             for (int j=a[i].l; j<=n; j+=lowbit(j)) ins(root[j],root[j],1,tot,t,1);
     80             
     81         }
     82     }
     83 }
     84 void clear()
     85 {
     86     tot=size=0;
     87     memset(root,0,sizeof(0));
     88     memset(rt,0,sizeof(0));
     89     memset(lt,0,sizeof(0));
     90     memset(sum,0,sizeof(0));
     91 }
     92 int main()
     93 {
     94     //freopen("dynrank1.in","r",stdin);
     95         clear();
     96         n=read(); m=read();
     97         for (int i=1; i<=n; i++) list[i]=h[i]=read();
     98         tot=n;
     99         for (int i=1; i<=m; i++)
    100         {
    101             scanf(" %c",&ch);
    102             a[i].l=read(); a[i].r=read();
    103             if (ch=='Q') a[i].val=read();
    104             else a[i].k=1,h[++tot]=list[tot]=a[i].r;
    105         } 
    106         sort(list+1,list+tot+1);
    107         for (int i=1; i<=tot; i++) h[i]=lower_bound(list+1,list+1+tot,h[i])-list;
    108         build();
    109         solve();
    110     return 0;
    111 }
    View Code
     
  • 相关阅读:
    c#队列的实现
    c#队列的实现
    C# 自定义控件制作和使用实例(winform)
    常见的位运算
    Clock()函数简单使用(C库函数)
    Python全局变量的简单使用
    PyQt5+Caffe+Opencv搭建人脸识别登录界面
    python3+pyqt5+opencv3简单使用
    OpenCV实现人脸检测
    opencv 截图并保存
  • 原文地址:https://www.cnblogs.com/HQHQ/p/5444319.html
Copyright © 2011-2022 走看看