zoukankan      html  css  js  c++  java
  • 主席树:动态 Kth

      1 /*zoj2112 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112
      2 动态 kth
      3 每一棵线段树是维护每一个序列前缀的值在任意区间的个数,
      4 如果还是按照静态的来做的话,那么每一次修改都要遍历O(n)棵树,
      5 时间就是O(2*M*nlogn)->TLE
      6 考虑到前缀和,我们通过树状数组来优化,即树状数组套主席树,
      7 每个节点都对应一棵主席树,那么修改操作就只要修改logn棵树,
      8 o(nlognlogn+Mlognlogn)时间是可以的,
      9 但是直接建树要nlogn*logn(10^7)会MLE
     10 我们发现对于静态的建树我们只要nlogn个节点就可以了,
     11 而且对于修改操作,只是修改M次,每次改变俩个值(减去原先的,加上现在的)
     12 也就是说如果把所有初值都插入到树状数组里是不值得的,
     13 所以我们分两部分来做,所有初值按照静态来建,内存O(nlogn),
     14 而修改部分保存在树状数组中,每次修改logn棵树,每次插入增加logn个节点
     15 O(M*logn*logn+nlogn)
     16 
     17 
     18 */
     19 #include<cstdio>
     20 #include<cstring>
     21 #include<cstdlib>
     22 #include<iostream>
     23 #include<algorithm>
     24 #include<vector>
     25 #include<cmath>
     26 #define ls(i) T[i].ls
     27 #define rs(i) T[i].rs
     28 #define w(i) T[i].w
     29 #define Find(i) (lower_bound(LX.begin(),LX.begin()+n1,i)-LX.begin())+1
     30 
     31 using namespace std;
     32 const int N=60000+10;
     33 struct node{
     34     int ls,rs,w;
     35     node(){ls=rs=w=0;}
     36 }T[2000000];
     37 struct ope{
     38     int i,l,r,k;
     39 }op[11000];
     40 vector<int> LX,Q1,Q2;
     41 int n,n1,m,cnt;
     42 int a[61000],root[61000*2];
     43 inline int lowbit(int x){
     44     return x&-x;
     45 }
     46 void build(int &i,int l,int r,int x){
     47     T[++cnt]=T[i]; i=cnt;
     48     w(i)++;
     49     if (l==r) return;
     50     int m=(l+r)>>1;
     51     if (x<=m) build(ls(i),l,m,x);
     52     else build(rs(i),m+1,r,x);
     53 }
     54 void ins(int &i,int l,int r,int x,int v){
     55     if (i==0){ T[++cnt]=T[i]; i=cnt; }
     56     w(i)+=v;
     57     if (l==r) return;
     58     int m=(l+r)>>1;
     59     if (x<=m) ins(ls(i),l,m,x,v);
     60     else ins(rs(i),m+1,r,x,v);
     61 }
     62 void my_ins(int pos,int x,int v){
     63     int t=Find(x);
     64     for (int i=pos;i<=n;i+=lowbit(i)){
     65         ins(root[i],1,n1,t,v);
     66     }
     67 }
     68 int Qy(vector<int> Q1,vector<int> Q2,int l,int r,int k){
     69     if (l==r) return l;
     70     int c=0;
     71     int m=(l+r)>>1;
     72     for (int i=0;i<Q1.size();i++) c-=w(ls(Q1[i]));
     73     for (int i=0;i<Q2.size();i++) c+=w(ls(Q2[i]));
     74     for (int i=0;i<Q1.size();i++) Q1[i]=(c>=k?ls(Q1[i]):rs(Q1[i]));
     75     for (int i=0;i<Q2.size();i++) Q2[i]=(c>=k?ls(Q2[i]):rs(Q2[i]));
     76 
     77     if (c>=k) return Qy(Q1,Q2,l,m,k);
     78     else return Qy(Q1,Q2,m+1,r,k-c);
     79 }
     80 void query(int l,int r,int k){
     81     Q1.clear();Q2.clear();
     82     Q1.push_back(root[l!=1?l-1+n:0]);
     83     Q2.push_back(root[r+n]);
     84     for (int i=l-1;i>0;i-=lowbit(i)) Q1.push_back(root[i]);
     85     for (int i=r;i>0;i-=lowbit(i)) Q2.push_back(root[i]);
     86 
     87     int t=Qy(Q1,Q2,1,n1,k);
     88     printf("%d\n",LX[t-1]);
     89 }
     90 void work(){
     91     cnt=0;
     92     //for (int i=0;i<n1;i++) cout<<list[i]<<" ";cout<<endl;
     93     memset(root,0,sizeof(root));
     94     for (int i=1;i<=n;i++){
     95         root[i+n]=root[i-1+n];
     96         int t=Find(a[i]);
     97         build(root[i+n],1,n1,t);
     98     }
     99     for (int i=0;i<m;i++){
    100         if (op[i].i==0){
    101             query(op[i].l,op[i].r,op[i].k);
    102         //    cout<<"*** "<<i<<endl;
    103         }else{
    104             my_ins(op[i].l,a[op[i].l],-1);
    105             my_ins(op[i].l,op[i].r,1);
    106             a[op[i].l]=op[i].r;
    107         }
    108     }
    109 
    110 }
    111 int main(){
    112     int Cas;scanf("%d",&Cas);
    113     while (Cas--){
    114         scanf("%d%d",&n,&m);
    115         LX.clear();
    116         for (int i=1;i<=n;i++){
    117             scanf("%d",&a[i]);LX.push_back(a[i]);
    118         }
    119         char s[10];
    120         for (int i=0;i<m;i++){
    121             scanf("%s",s);
    122             if (s[0]=='Q'){
    123                 op[i].i=0;
    124                 scanf("%d%d%d",&op[i].l,&op[i].r,&op[i].k);
    125             }else{
    126                 op[i].i=1;
    127                 scanf("%d%d",&op[i].l,&op[i].r);
    128                 LX.push_back(op[i].r);
    129             }
    130         }
    131         sort(LX.begin(),LX.end());
    132         n1=unique(LX.begin(),LX.end())-LX.begin();
    133         work();
    134     }
    135 
    136 
    137     return 0;
    138 }
  • 相关阅读:
    今日进度
    今日进度
    今日进度
    今日进度
    今日进度
    每周总结
    今日进度
    python设置环境变量
    Python Property属性【python风格】
    学习-robot【字符串汇总】
  • 原文地址:https://www.cnblogs.com/Rlemon/p/3096264.html
Copyright © 2011-2022 走看看