堆/平衡树——Luogu1801 黑匣子_NOI导刊2010提高(06)
2017-04-07 08:30
197 查看
https://www.luogu.org/problem/show?pid=1801
那个,这个标题一开始我以为是飞机上的黑匣子。。。
进入正题,输出第k小
我们来脑洞大开一下,因为k是递增的,所以过程相当于不可逆
那么我们可以考虑开两个二叉堆,一个小根堆,一个大根堆
我们限制大根堆的大小为k-1(即要求的第k小-1)
每次插入先入大根堆,如果大根堆大小超过k-1,把大根堆顶的数扔到小根堆里去
询问时输出小根堆顶即可,然后大根堆大小+1,把这个数扔过去就好了
正确性显然
其实啊,非区间k值这种问题交给平衡树最好了。。。
只有插入和询问的splay奉上(虽然没前面那个快。。。)
那个,这个标题一开始我以为是飞机上的黑匣子。。。
进入正题,输出第k小
我们来脑洞大开一下,因为k是递增的,所以过程相当于不可逆
那么我们可以考虑开两个二叉堆,一个小根堆,一个大根堆
我们限制大根堆的大小为k-1(即要求的第k小-1)
每次插入先入大根堆,如果大根堆大小超过k-1,把大根堆顶的数扔到小根堆里去
询问时输出小根堆顶即可,然后大根堆大小+1,把这个数扔过去就好了
正确性显然
#include<bits/stdc++.h> using namespace std; priority_queue<int>q1; priority_queue<int,vector<int>,greater<int> >q2; int a[200001],k,r,cnt=0; inline void insert(int x){ q1.push(x); while(q1.size()>cnt){ q2.push(q1.top()); q1.pop(); } } inline int find(){ cnt++;int ans=q2.top(); q1.push(ans); q2.pop();return ans; } int main() { k=0,r=0; int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++){ int x;scanf("%d",&x); for(;r<x;r++)insert(a[r+1]); printf("%d\n",find());k++; } return 0; }
其实啊,非区间k值这种问题交给平衡树最好了。。。
只有插入和询问的splay奉上(虽然没前面那个快。。。)
#include<bits/stdc++.h> using namespace std; int a[200001]; int t[1000001][2],fa[1000001],s[1000001],val[1000001],v[1000001]; int n,m,tt,rt,del,pr,su; inline void pushup(int x){s[x]=s[t[x][0]]+s[t[x][1]]+v[x];} inline void turn(int x,int &p){ int y=fa[x],z=fa[y],l,r; if(t[y][0]==x)l=0;else l=1; r=l^1; if(y==p)p=x; else if(t[z][0]==y)t[z][0]=x; else t[z][1]=x; fa[x]=z;fa[y]=x;fa[t[x][r]]=y; t[y][l]=t[x][r];t[x][r]=y; pushup(y);pushup(x); } inline void splay(int x,int &p){ int y,z;while(x!=p){ y=fa[x];z=fa[y]; if(y!=p){ if((t[y][0]==x)^(t[z][0]==y))turn(x,p); else turn(y,p); } turn(x,p); } } inline void insert(int k){ if(!rt){ tt++;rt=tt; val[tt]=k;s[tt]=v[tt]=1; return; } int p=rt,z; while(p){ z=p;s[p]++; if(k<val[p])p=t[p][0]; else if(k>val[p])p=t[p][1]; else{v[p]++;pushup(p);splay(p,rt);return;} } if(val[z]>k)t[z][0]=++tt; else t[z][1]=++tt; val[tt]=k;s[tt]=v[tt]=1;fa[tt]=z; splay(tt,rt); } inline int find(int x,int k){ if(k<=s[t[x][0]])return find(t[x][0],k); if(k>s[t[x][0]]&&k<=s[t[x][0]]+v[x])return val[x]; return find(t[x][1],k-s[t[x][0]]-v[x]); } int main() { int k=0,r=0; int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++){ int x;scanf("%d",&x); for(;r<x;r++)insert(a[r+1]); k++;printf("%d\n",find(rt,k)); } return 0; }
相关文章推荐
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)
- 洛谷P1801 黑匣子_NOI导刊2010提高(06)
- 堆or优先队列(洛谷1801 黑匣子_NOI导刊2010提高(06))
- 洛谷 P1801 [NOI导刊2010提高(06)] 黑匣子
- 洛谷P1801 黑匣子_NOI导刊2010提高(06)
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)
- NOI导刊2010提高(06) 黑匣子
- 黑匣子_NOI导刊2010提高(06)(对顶堆)
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)
- 刷题记录-luoguP1801 黑匣子_NOI导刊2010提高(06)
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)
- P1801 黑匣子_NOI导刊2010提高(06)
- 洛谷1801 黑匣子_NOI导刊2010提高(06) 【好题】
- P1801 黑匣子_NOI导刊2010提高(06)
- LUOGUP1801 黑匣子_NOI导刊2010提高(06)
- 洛谷P1801 黑匣子_NOI导刊2010提高(06)
- 洛谷P1801 黑匣子_NOI导刊2010提高(06)
- |洛谷|NOI导刊|堆|黑匣子_NOI导刊2010提高(06)
- 【P1806】黑匣子_NOI导刊2010提高(06) splay
- 黑匣子_NOI导刊2010提高(06) 洛谷p1801