动态 K th

  每一棵线段树是维护每一个序列前缀的值在任意区间的个数,如果还是按照静态的来做的话,那么每一次修改都要遍历O(n)棵树,时间就是O(2*M*nlogn)->TLE考虑到前缀和,我们通过树状数组来优化,即树状数组套主席树,每个节点都对应一棵主席树,那么修改操作就只要修改logn棵树,o(nlognlogn+Mlognlogn)时间是可以的,但是直接建树要nlogn*logn(10^7)会MLE我们发现对于静态的建树我们只要nlogn个节点就可以了,而且对于修改操作,只是修改M次,每次改变俩个值(减去原先的,加上现在的)也就是说如果把所有初值都插入到树状数组里是不值得的,所以我们分两部分来做,所有初值按照静态来建,内存O(nlogn),而修改部分保存在树状数组中,每次修改logn棵树,每次插入增加logn个节点O(M*logn*logn+nlogn)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<vector>
  7 #include<cmath>
  8 #define ls(i) T[i].ls
  9 #define rs(i) T[i].rs
 10 #define w(i) T[i].w
 11 #define Find(i) (lower_bound(LX.begin(),LX.begin()+n1,i)-LX.begin())+1
 12
 13 using namespace std;
 14 const int N=60000+10;
 15 struct node{
 16     int ls,rs,w;
 17     node(){ls=rs=w=0;}
 18 }T[2000000];
 19 struct ope{
 20     int i,l,r,k;
 21 }op[11000];
 22 vector<int> LX,Q1,Q2;
 23 int n,n1,m,cnt;
 24 int a[61000],root[61000*2];
 25 inline int lowbit(int x){
 26     return x&-x;
 27 }
 28 void build(int &i,int l,int r,int x){
 29     T[++cnt]=T[i]; i=cnt;
 30     w(i)++;
 31     if (l==r) return;
 32     int m=(l+r)>>1;
 33     if (x<=m) build(ls(i),l,m,x);
 34     else build(rs(i),m+1,r,x);
 35 }
 36 void ins(int &i,int l,int r,int x,int v){
 37     if (i==0){ T[++cnt]=T[i]; i=cnt; }
 38     w(i)+=v;
 39     if (l==r) return;
 40     int m=(l+r)>>1;
 41     if (x<=m) ins(ls(i),l,m,x,v);
 42     else ins(rs(i),m+1,r,x,v);
 43 }
 44 void my_ins(int pos,int x,int v){
 45     int t=Find(x);
 46     for (int i=pos;i<=n;i+=lowbit(i)){
 47         ins(root[i],1,n1,t,v);
 48     }
 49 }
 50 int Qy(vector<int> Q1,vector<int> Q2,int l,int r,int k){
 51     if (l==r) return l;
 52     int c=0;
 53     int m=(l+r)>>1;
 54     for (int i=0;i<Q1.size();i++) c-=w(ls(Q1[i]));
 55     for (int i=0;i<Q2.size();i++) c+=w(ls(Q2[i]));
 56     for (int i=0;i<Q1.size();i++) Q1[i]=(c>=k?ls(Q1[i]):rs(Q1[i]));
 57     for (int i=0;i<Q2.size();i++) Q2[i]=(c>=k?ls(Q2[i]):rs(Q2[i]));
 58
 59     if (c>=k) return Qy(Q1,Q2,l,m,k);
 60     else return Qy(Q1,Q2,m+1,r,k-c);
 61 }
 62 void query(int l,int r,int k){
 63     Q1.clear();Q2.clear();
 64     Q1.push_back(root[l!=1?l-1+n:0]);
 65     Q2.push_back(root[r+n]);
 66     for (int i=l-1;i>0;i-=lowbit(i)) Q1.push_back(root[i]);
 67     for (int i=r;i>0;i-=lowbit(i)) Q2.push_back(root[i]);
 68
 69     int t=Qy(Q1,Q2,1,n1,k);
 70     printf("%d\n",LX[t-1]);
 71 }
 72 void work(){
 73     cnt=0;
 74     //for (int i=0;i<n1;i++) cout<<list[i]<<" ";cout<<endl;
 75     memset(root,0,sizeof(root));
 76     for (int i=1;i<=n;i++){
 77         root[i+n]=root[i-1+n];
 78         int t=Find(a[i]);
 79         build(root[i+n],1,n1,t);
 80     }
 81     for (int i=0;i<m;i++){
 82         if (op[i].i==0){
 83             query(op[i].l,op[i].r,op[i].k);
 84         //    cout<<"*** "<<i<<endl;
 85         }else{
 86             my_ins(op[i].l,a[op[i].l],-1);
 87             my_ins(op[i].l,op[i].r,1);
 88             a[op[i].l]=op[i].r;
 89         }
 90     }
 91
 92 }
 93 int main(){
 94     int Cas;scanf("%d",&Cas);
 95     while (Cas--){
 96         scanf("%d%d",&n,&m);
 97         LX.clear();
 98         for (int i=1;i<=n;i++){
 99             scanf("%d",&a[i]);LX.push_back(a[i]);
100         }
101         char s[10];
102         for (int i=0;i<m;i++){
103             scanf("%s",s);
104             if (s[0]==‘Q‘){
105                 op[i].i=0;
106                 scanf("%d%d%d",&op[i].l,&op[i].r,&op[i].k);
107             }else{
108                 op[i].i=1;
109                 scanf("%d%d",&op[i].l,&op[i].r);
110                 LX.push_back(op[i].r);
111             }
112         }
113         sort(LX.begin(),LX.end());
114         n1=unique(LX.begin(),LX.end())-LX.begin();
115         work();
116     }
117
118
119     return 0;
120 }

转自:http://www.cnblogs.com/Rlemon/archive/2013/05/24/3096264.html

时间: 2024-10-05 09:34:56

动态 K th的相关文章

【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题

达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状数组,而我一开始根本不知道该怎么套,, 学习吧,,, 然后我自己脑补如果不套会如何?后来想到是查询O(logn),修改是O(nlogn),很明显修改的复杂度太大了,为了降低修改的复杂度,我们只得套上树状数组来维护前缀和使它的n的复杂度降低为logn,从而修改的复杂度变为O(log2n).但因为我们套

COJ 0986 WZJ的数据结构(负十四) 区间动态k大

题解:哈哈哈我过了!!!主席树+树状数组写起来还真是hentai啊... 在这里必须分享我的一个沙茶错!!!看这段代码: void get(int x,int d){ if(!d)for(lt[ltot=1]=root[x];x;x-=x&-x)if(c[x])lt[++ltot]=c[x]; else for(rt[rtot=1]=root[x];x;x-=x&-x)if(c[x])rt[++rtot]=c[x];return; } 似乎挺正常是吧?而且缩进也很优美对不对!!! 可是!!

深度学习用于文本分类的论文及代码集锦

深度学习用于文本分类的论文及代码集锦 原创: FrankLearningMachine 机器学习blog 4天前 [1] Convolutional Neural Networks for Sentence Classification Yoon Kim New York University EMNLP 2014 http://www.aclweb.org/anthology/D14-1181 这篇文章主要利用CNN基于预训练好的词向量中对句子进行分类.作者发现利用微调来学习任务相关的词向量可

融合后如何如何后如何如何

http://ypk.39.net/search/all?k=%A6%C6%B6%F5%D6%DD%C4%C4%C0%EF%C2%F2%C3%C0%C9%B3%CD%AAQ%A3%BA%A3%B8%A3%B6%A3%B3%A3%B9%A3%B0%A3%B2%A3%B9%A3%B6%A3%B2%A1%C6 http://ypk.39.net/search/all?k=%A8z%BE%A3%C3%C5%C4%C4%C0%EF%C2%F2%C3%C0%C9%B3%CD%AAQ%A3%BA%A3%B8%

哥哥ukulele

http://ypk.39.net/search/all?k=%A1%FB%C6%CE%CC%EF%C4%C4%C0%EF%D3%D0%B0%B2%C0%D6%CB%C0%D2%A9%C2%F4Q%A3%BA%A3%B8%A3%B6%A3%B3%A3%B9%A3%B0%A3%B2%A3%B9%A3%B6%A3%B2%A1%BC http://ypk.39.net/search/all?k=%A1%D3%B8%A3%C7%E5%C4%C4%C0%EF%D3%D0%B0%B2%C0%D6%CB%C0

ZOJ2112--Dynamic Rankings (动态区间第k大)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap

Dynamic Rankings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 Description The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query l

zoj2112 主席树动态第k大 (主席树&amp;&amp;树状数组)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

HDU 2852 KiKi&#39;s K-Number(动态过程求第K小数)

题意: 给出三种操作, 0 在容器中插入一个数. 1 在容器中删除一个数. 2 求出容器中大于a的第k大元素. 思路:可以用树状数组和线段树,显然a[1]+...+a[i]随i有明显的单调性,所以可以二分出答案 线段树时间复杂度比树状数组的常数大了几倍...所以线段树擦边过了 还有另外一种思路:二分只是二分出a[1]+...+a[i]的上界i,所以可以逆向考虑,从a[1]开始累加,直到到达k,这样的复杂度就由原来的 O(lgN*lgN) 变成O(lgN)了.难在累加的过程,线段树和树状数组是同样