[洛谷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;
}