分析:这题和另外一个题目中位数非常相似,有兴趣可以先看看,比这一题简单。首先暴力模拟还是别想了,估计30%的数据都有点悬。正解应该是用二叉堆。但是如果用一个堆当然不方便,所以建两个堆,一个大根堆,一个小根堆,每次只要出现询问操作,就把小根堆的堆顶丢进大根堆中维护,然后输出就可以了,但是要注意,操作过程中一定要让大根堆的堆顶小于小根队的堆顶,也就是保证大根堆中的元素就是题目中的前i小的元素。这样题目就变的非常容易了。
Code:
//It is made by HolseLee on 18th Mar 2018 //Luogu.org P1801 #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<iomanip> #include<algorithm> using namespace std; const int N=2e5+7; int n,m,opt[N],a[N]; int hmax[N],hmin[N]; int sizex,sizen; inline int read() { char ch=getchar();int num=0;bool flag=false; while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)flag=true;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){num=num*10+ch-‘0‘;ch=getchar();} return flag?-num:num; } inline void insert_min(int x) { hmin[++sizen]=x; int ka=sizen; while(ka>1){ if(hmin[ka]<hmin[ka/2]){ swap(hmin[ka],hmin[ka/2]); ka/=2;} else break; } } inline void insert_max(int x) { hmax[++sizex]=x; int ka=sizex; while(ka>1){ if(hmax[ka]>hmax[ka/2]){ swap(hmax[ka],hmax[ka/2]); ka/=2;} else break; } } inline void delet_min() { hmin[1]=hmin[sizen--]; int ka=1,s=ka*2; while(s<=sizen){ if(s<sizen&&hmin[s+1]<hmin[s]) s++; if(hmin[s]<hmin[ka]){ swap(hmin[s],hmin[ka]); ka=s;s=ka*2;} else break; } } inline void delet_max() { hmax[1]=hmax[sizex--]; int ka=1,s=ka*2; while(s<=sizex){ if(s<sizex&&hmax[s+1]>hmax[s]) s++; if(hmax[s]>hmax[ka]){ swap(hmax[s],hmax[ka]); ka=s;s=ka*2;} else break; } } inline int change() { int ka=hmin[1]; delet_min(); insert_max(ka); return ka; } int main() { bool flag=false; n=read();m=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=m;i++){ int x=read();opt[x]++;} for(int i=1;i<=n;i++){ insert_min(a[i]); if(flag&&hmin[1]<hmax[1]){ int minn=hmin[1]; int maxx=hmax[1]; delet_min();insert_min(maxx); delet_max();insert_max(minn); } while(opt[i]>0){ flag=true;opt[i]--; int ans=change(); printf("%d\n",ans); } } return 0; }