洛谷 3871 [TJOI2010]中位數
阿新 • • 發佈:2018-11-08
【題解】
平衡樹模板題,不過因為可以離線,所以有別的做法。把詢問倒著做,變成刪掉數字、求中位數,於是可以二分+樹狀陣列。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 #define rg register 6 #define N 500010 7 using namespace std; 8 int n,m,cnt,top,b[N],t[N],ans[N]; 9 struct rec{ 10 intnum,pos; 11 }a[N]; 12 struct que{ 13 int opt,num; 14 }q[N]; 15 inline int read(){ 16 int k=0,f=1; char c=getchar(); 17 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 18 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 19 return k*f; 20 } 21 inline void add(intx,int y){for(;x<=n;x+=x&-x)t[x]+=y;} 22 inline int query(int x){int ret=0;for(;x;x-=x&-x)ret+=t[x]; return ret;} 23 inline int search(int x){ 24 int l=0,r=n; 25 while(l+1<r){ 26 int mid=(l+r)>>1; 27 if(query(mid)>=x) r=mid; else l=mid; 28 } 29 // printf("l=%d r=%d\n",l,r);30 return r; 31 } 32 inline bool cmp(rec a,rec b){return a.num<b.num;} 33 int main(){ 34 n=read(); 35 for(rg int i=1;i<=n;i++) a[i].num=read(); 36 m=read(); 37 for(rg int i=1;i<=m;i++){ 38 char c=getchar(); 39 while(c!='a'&&c!='m') c=getchar(); 40 if(c=='a'){ 41 q[i].opt=1,q[i].num=a[++n].num=read(); 42 a[n].pos=i; 43 } 44 else q[i].opt=2; 45 } 46 sort(a+1,a+1+n,cmp); 47 for(rg int i=1;i<=n;i++) add(i,1); 48 for(rg int i=1;i<=n;i++)if(a[i].pos) b[a[i].pos]=i; 49 // printf("n=%d\n",n); 50 for(rg int i=m;i;i--){ 51 if(q[i].opt==1){ 52 add(b[i],-1); cnt++; 53 } 54 else ans[++top]=a[search((n-cnt)/2+(n-cnt)%2)].num; 55 } 56 while(top) printf("%d\n",ans[top--]); 57 return 0; 58 }