[洛谷P2617] Dynamic Rankings

前言

整体二分永远滴神!

树套树?*都不写。

题目

洛谷

讲解

把初始序列当成加入数字,修改当成删除+加入数字。

二分的是答案,考虑二分出来一个值之后所有数字其实都变成了01,所以不用离散化,可以直接上小常数树状数组。

好久没打整体二分都忘了询问放到右边要减去左边的贡献了= =

代码

超短代码~
//12252024832524
#include <cstdio>
#include <cstring>
#include <algorithm>
#define TT template<typename T>
using namespace std; 

typedef long long LL;
const int MAXN = 300005;
int n,m,cnt,qtot;
int a[MAXN],ans[MAXN];

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

struct node
{
	int opt,l,r,k,ID;
	//  opt pos f val 0
}t[MAXN],tl[MAXN],tr[MAXN];
int b[MAXN];
int lowbit(int x){return x & -x;}
void Add(int x,int val){for(int i = x;i <= n;i += lowbit(i)) b[i] += val;}
int Sum(int x){int ret = 0;for(int i = x;i >= 1;i -= lowbit(i)) ret += b[i];return ret;}
void solve(int l,int r,int x,int y)
{
	if(l == r){for(int i = x;i <= y;++ i) if(t[i].ID) ans[t[i].ID] = l;return;}
	int mid = (l+r) >> 1,cl = 0,cr = 0,ql = 0,qr = 0;
	for(int i = x;i <= y;++ i)
	{
		if(!t[i].opt)
		{
			if(t[i].k <= mid) Add(t[i].l,t[i].r),tl[++cl] = t[i];
			else tr[++cr] = t[i];
		}
		else
		{
			int c = Sum(t[i].r) - Sum(t[i].l-1);
			if(c >= t[i].k) tl[++cl] = t[i],ql = 1;
			else tr[++cr] = t[i],tr[cr].k -= c,qr = 1;
		}
	}
	for(int i = x;i <= y;++ i) if(!t[i].opt && t[i].k <= mid) Add(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(ql) solve(l,mid,x,x+cl-1);
	if(qr) solve(mid+1,r,x+cl,y);
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n = Read(); m = Read();
	for(int i = 1;i <= n;++ i) a[i] = Read(),t[++cnt] = {0,i,1,a[i],0};
	for(int i = 1;i <= m;++ i)
	{
		char c = getchar(); while(c != 'Q' && c != 'C') c = getchar();
		int x = Read(),y = Read();
		if(c == 'Q') t[++cnt] = {1,x,y,Read(),++qtot};
		else t[++cnt] = {0,x,-1,a[x],0},t[++cnt] = {0,x,1,a[x]=y,0};
	}
	solve(0,1e9,1,cnt);
	for(int i = 1;i <= qtot;++ i) Put(ans[i],'\n');
	return 0;
}
posted @ 2021-09-10 16:16  皮皮刘  阅读(42)  评论(0编辑  收藏  举报