[luogu] P2617 Dynamic Rankings

整体二分模板,所谓整体二分其实就是将修改与询问保存下来,然后二分值域

树套树亦可,但是码量较大;

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;const int N=1e5+7;typedef long long ll;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9')	{if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')	{x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
struct Query
{
	int o,l,r,k,i;
	Query(int o=0,int l=0,int r=0,int k=0,int i=0)
	{this->o=o;this->l=l;this->r=r;this->k=k;this->i=i;}
}q[N<<2],q1[N<<2],q2[N<<2];int n,m,c[N],w[N],res[N];
inline int lowbit(int x){return x&(-x);}
inline void add(int x,int y){for(int i=x;i<=n;i+=lowbit(i))c[i]+=y;}
inline int sum(int x){int res=0;while(x)res+=c[x],x-=lowbit(x);return res;}
inline void solve(int s,int t,int l,int r)
{
	if(l==r)
	{
		for(int i=s;i<=t;i++)
		if(q[i].o==2)res[q[i].i]=l;
		return;
	}int mid=(l+r)>>1,cnt1=0,cnt2=0;
	for(int i=s;i<=t;i++)
	{
		if(q[i].o==1)
		{
			if(q[i].l<=mid) add(q[i].i,q[i].r),q1[++cnt1]=q[i];
			else q2[++cnt2]=q[i];
		}
		else
		{
			int x=sum(q[i].r)-sum(q[i].l-1);
			if(x>=q[i].k) q1[++cnt1]=q[i];
			else q[i].k-=x,q2[++cnt2]=q[i];
		}
	}
	for(int i=1;i<=cnt1;i++)
	if(q1[i].o==1)add(q1[i].i,-q1[i].r);
	for(int i=1;i<=cnt1;i++) q[s+i-1]=q1[i];
	for(int i=1;i<=cnt2;i++) q[s+cnt1+i-1]=q2[i];
	if(cnt1) solve(s,s+cnt1-1,l,mid);
	if(cnt2) solve(s+cnt1,t,mid+1,r);
}
int main()
{
	n=read(),m=read();int cnt=0,tot=0;
	for(int i=1;i<=n;i++) q[++cnt]=Query(1,w[i]=read(),1,0,i);
	for(int i=1;i<=m;i++)
	{
		char ch;cin>>ch;
		if(ch=='Q') q[++cnt].o=2,q[cnt].l=read(),q[cnt].r=read(),q[cnt].k=read(),q[cnt].i=++tot;
		else
		{
			int l=read(),r=read();
			q[++cnt]=Query(1,w[l],-1,0,l);
			q[++cnt]=Query(1,w[l]=r,1,0,l);
		}
	}solve(1,cnt,0,1e9+1);
	for(int i=1;i<=tot;i++)	cout<<res[i]<<endl;
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/chtomede/p/12082942.html
今日推荐