Dynamic Rankings

題目鏈接:Dynamic Rankings


樹狀數組套主席樹版本的已經寫過了,現在就寫一個整體二分的。

注意把最初的序列也當成操作就好了。


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=4e5+10;
int n,m,cnt,res[N],a[N],idx,d[N];
struct node{int op,l,r,k,id;}t[N],tl[N],tr[N];
inline void insert(int x,int v){for(;x<=n;x+=x&(-x)) d[x]+=v;}
inline int ask(int x){int s=0; for(;x;x-=x&(-x)) s+=d[x]; return s;}
void solve(int l,int r,int x,int y){
	if(l==r){for(int i=x;i<=y;i++)	if(t[i].id)	res[t[i].id]=l;	return ;}
	int mid=l+r>>1,fl=0,fr=0,cl=0,cr=0;
	for(int i=x;i<=y;i++){
		if(t[i].op==0){
			if(t[i].k<=mid)	insert(t[i].l,t[i].r),tl[++cl]=t[i];
			else	tr[++cr]=t[i];
		}else{
			int num=ask(t[i].r)-ask(t[i].l-1);
			if(num>=t[i].k)	fl=1,tl[++cl]=t[i];
			else	fr=1,tr[++cr]=t[i],tr[cr].k-=num;
		}
	}
	for(int i=x;i<=y;i++)	if(t[i].op==0&&t[i].k<=mid) insert(t[i].l,-t[i].r);
	for(int i=1;i<=cl;i++)	t[x+i-1]=tl[i];
	for(int i=1;i<=cr;i++)	t[x+cl+i-1]=tr[i];
	if(fl)	solve(l,mid,x,x+cl-1);
	if(fr)	solve(mid+1,r,x+cl,y);
}
signed main(){
	ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
	cin>>n>>m;
	for(int i=1;i<=n;i++)	cin>>a[i],t[++cnt]={0,i,1,a[i],0};
	for(int i=1,x,y,k;i<=m;i++){
		char d;	cin>>d>>x>>y;
		if(d=='C')	t[++cnt]={0,x,-1,a[x],0},t[++cnt]={0,x,1,y,0},a[x]=y;
		else	cin>>k,t[++cnt]={1,x,y,k,++idx};
	}
	solve(0,1e9,1,cnt);
	for(int i=1;i<=idx;i++)	cout<<res[i]<<'\n';
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章