zoukankan      html  css  js  c++  java
  • 【BZOJ1901】Dynamic Rankings

    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

     输出文件应包含T行。对于每一组数据,如果该关卡有解,输出一行Yes;否则输出一行No。

    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。

    【分析】

    裸的主席树,直接上模板就行了。

      1 /**************************************************************
      2     Problem: 1901
      3     User: TCtower
      4     Language: C++
      5     Result: Accepted
      6     Time:612 ms
      7     Memory:24988 kb
      8 ****************************************************************/
      9  
     10 #include <iostream>
     11 #include <cstring>
     12 #include <cstdio>
     13 #include <cmath>
     14 #include <cstring>
     15 #include <algorithm>
     16 #include <vector>
     17 //#define LOCAL
     18 const int maxn=10000+5;
     19 const int INF=99999999;
     20 const int maxnode=2000000+10; 
     21 using namespace std;
     22 struct OP
     23 {
     24        int type;//0代表询问,1代表改变 
     25        int l,r,k;
     26 }op[maxn];
     27 //点结构体 
     28 struct node
     29 {
     30        int ls,rs,w;
     31        node(){ls=rs=w=0;}
     32 }T[maxnode];
     33 vector<int>LX;
     34 vector<int>Q1,Q2;
     35 int a[maxn],n,q,n1;
     36 int cnt,root[maxn*2]; 
     37  
     38 void init();
     39 void work();
     40 //树状数组用 
     41 inline int lowbit(int i){return i&-i;}
     42 inline int find(int i)
     43 {
     44        //二分查找不解释 
     45        return (lower_bound(LX.begin(),LX.begin()+n1,i)-LX.begin())+1;
     46 }
     47 void build(int &i,int l,int r,int val);
     48 void query(int l,int r,int k);//区间第k大 
     49 //其实我觉得不传副本速度会上升? 
     50 int Qy(vector<int>Q1,vector<int>Q2,int l,int r,int k);
     51 void my_ins(int pos,int x,int v);
     52 void ins(int &i,int l,int r,int x,int v);
     53  
     54 int main() 
     55 {
     56     #ifdef LOCAL 
     57     freopen("data.txt","r",stdin);
     58     freopen("out.txt","w",stdout);
     59     #endif
     60     init();//读入与初始化 
     61     work();
     62     return 0;
     63 }
     64 void init()
     65 {
     66     scanf("%d%d",&n,&q);
     67     LX.clear();
     68     for (int i=1;i<=n;i++)
     69     {
     70         scanf("%d",&a[i]);        
     71         LX.push_back(a[i]);
     72     }
     73     char str[10];
     74     for (int i=1;i<=q;i++)
     75     {
     76         scanf("%s",str);
     77         if (str[0]=='Q')
     78         {
     79             op[i].type=0;
     80             scanf("%d%d%d",&op[i].l,&op[i].r,&op[i].k);
     81         }
     82         else
     83         {
     84             op[i].type=1;
     85             scanf("%d%d",&op[i].l,&op[i].r);
     86             LX.push_back(op[i].r);
     87         }
     88     }
     89     sort(LX.begin(),LX.end());
     90     n1=unique(LX.begin(),LX.end())-LX.begin();
     91 }
     92 void ins(int &i,int l,int r,int x,int v)
     93 {
     94      if (i==0) {T[++cnt]=T[i];i=cnt;}//没有创建过新的节点
     95      T[i].w+=v;
     96      if (l==r) return;
     97      int mid=(l+r)>>1;
     98      if (x<=mid) ins(T[i].ls,l,mid,x,v);
     99      else ins(T[i].rs,mid+1,r,x,v); 
    100 }
    101 void my_ins(int pos,int x,int v)
    102 {
    103      int t=find(x);//找到x的位置
    104      for (int i=pos;i<=n;i+=lowbit(i))
    105      {
    106          ins(root[i],1,n1,t,v);
    107      } 
    108 }
    109 int Qy(vector<int>Q1,vector<int>Q2,int l,int r,int k) 
    110 {
    111     if (l==r) return l;
    112     int c=0,mid=(l+r)>>1;
    113     //这两句可以互换,统计总数 
    114     for (int i=0;i<Q1.size();i++) c-=T[T[Q1[i]].ls].w;
    115     for (int i=0;i<Q2.size();i++) c+=T[T[Q2[i]].ls].w;
    116     //大于k说明在左子树中而不右子树 
    117     for (int i=0;i<Q1.size();i++) Q1[i]=(c>=k?T[Q1[i]].ls:T[Q1[i]].rs);
    118     for (int i=0;i<Q2.size();i++) Q2[i]=(c>=k?T[Q2[i]].ls:T[Q2[i]].rs);
    119     if (c>=k) return Qy(Q1,Q2,l,mid,k);//继续向下寻找 
    120     else return Qy(Q1,Q2,mid+1,r,k-c);
    121 } 
    122 void query(int l,int r,int k)
    123 {
    124      Q1.clear();Q2.clear();//临时队列清空
    125      Q1.push_back(root[l!=1?l-1+n:0]);
    126      Q2.push_back(root[r+n]); 
    127      for (int i=l-1;i;i-=lowbit(i)) Q1.push_back(root[i]);
    128      for (int i=r;i;i-=lowbit(i)) Q2.push_back(root[i]);
    129      int t=Qy(Q1,Q2,1,n1,k);
    130      printf("%d
    ",LX[t-1]);
    131 } 
    132 void work()
    133 {
    134      cnt=0;
    135      memset(root,0,sizeof(root));
    136      for (int i=1;i<=n;i++)
    137      {
    138          root[i+n]=root[i+n-1];
    139          int t=find(a[i]);
    140          build(root[i+n],1,n1,t);
    141      }
    142      for (int i=1;i<=q;i++)
    143      {
    144          if (op[i].type==0)
    145          query(op[i].l,op[i].r,op[i].k);
    146          else
    147          {
    148               my_ins(op[i].l,a[op[i].l],-1);
    149               my_ins(op[i].l,op[i].r,1);
    150               //修改 
    151               a[op[i].l]=op[i].r;
    152          }         
    153      }
    154 } 
    155 void build(int &i,int l,int r,int val)
    156 {
    157      //对于修改过的每一个点
    158      //都要新建一个副本 
    159      T[++cnt]=T[i];i=cnt;
    160      T[i].w++;
    161      if (l==r) return;
    162      int mid=(l+r)>>1;
    163      //按值建线段树 
    164      if (val<=mid) build(T[i].ls,l,mid,val);
    165      else build(T[i].rs,mid+1,r,val);
    166 }
  • 相关阅读:
    centos7.6进行软raid5制作
    面试题 PHP1
    基于githooks利用PHP_CodeSniffer做PSR2代码风格规范检测
    【GC 分代收集算法 VS 分区收集算法】
    【 Redis五大数据类型实现原理】
    【Java反射】
    【GC 垃圾收集器】
    【Redis过期策略/内存淘汰机制/对过期Key的处理】
    【Redis底层数据结构】
    【当骗子遇上研发工程师,还没开始就已经结束】
  • 原文地址:https://www.cnblogs.com/hoskey/p/3892357.html
Copyright © 2011-2022 走看看