P2617 Dynamic Rankings | 整体二分
题目简述
给一个长度为\(n\)的序列\(a_1,a_2,\cdots a_n\),有\(m\)个操作,为以下两种:
- \(x,k\) \(a_x \leftarrow k\)
- \(l,r,k\) 求区间\([l,r]\)内的第\(k\)小
\(n,m \le 10^5\).
简单口胡
首先这题毒瘤数据结构是完全可做的。
但是考虑到我可能不会,于是整体二分。
有修改的整体二分其实和无修的差不多,多了一个将原来的改为\(-1\)的过程。
# include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n,m;
int a[N << 1];
struct node
{
int l,r,k,type,soc;
node(){}
node(int _l,int _r,int _k,int _ty,int _soc) : l(_l),r(_r),k(_k),type(_ty),soc(_soc) {}
}Q[N << 1],q1[N << 1],q2[N << 1];
int tot = 0,qtot = 0,ans[N << 1];
struct BIT
{
int lowbit(int x) {return x & (-x);}
int a[N];
void add(int x,int d) {while(x <= n) {a[x] += d;x += lowbit(x);}}
int query(int x)
{
int ans = 0;
while(x) {ans += a[x];x -= lowbit(x);}
return ans;
}
}T;
template <typename T> void read(T &x)
{
int w = 1;
x = 0;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') w = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
x *= w;
}
template <typename T> void write(T x)
{
if(x < 0) x = -x;
if(x >= 10) write(x / 10);
char ch = (x % 10) + 48;
putchar(ch);
return;
}
void qfind(int l,int r,int s,int t)
{
if(l > r || s > t) return;
if(l == r)
{
for(int i = s; i <= t; i++)
{
if(Q[i].type == 2) ans[Q[i].soc] = l;
}
return;
}
int mid = (l + r) >> 1;
int cur1 = 0,cur2 = 0;
for(int i = s; i <= t; i++)
{
if(Q[i].type == 1)
{
if(Q[i].l <= mid)
{
T.add(Q[i].soc,Q[i].k);
q1[++cur1] = Q[i];
}
else q2[++cur2] = Q[i];
}
else
{
int sum = T.query(Q[i].r) - T.query(Q[i].l - 1);
if(sum >= Q[i].k)
{
q1[++cur1] = Q[i];
}
else
{
Q[i].k -= sum;
q2[++cur2] = Q[i];
}
}
}
for(int i = 1; i <= cur1; i++)
{
if(q1[i].type == 1)
{
T.add(q1[i].soc,-q1[i].k);
}
}
for(int i = 1; i <= cur1; i++) Q[s + i - 1] = q1[i];
for(int i = 1; i <= cur2; i++) Q[s + i + cur1 - 1] = q2[i];
qfind(l,mid,s,s + cur1 - 1);
qfind(mid + 1,r,s + cur1,t);
return;
}
int main(void)
{
read(n),read(m);
for(int i = 1; i <= n; i++)
{
read(a[i]);
Q[++tot] = node(a[i],0,1,1,i);
}
for(int i = 1; i <= m; i++)
{
char opt[2];
scanf("%s",opt);
int l,r,k;
if(opt[0] == 'C')
{
read(l),read(k);
Q[++tot] = node(a[l],0,-1,1,l);
Q[++tot] = node(a[l] = k,0,1,1,l);
}
else
{
read(l),read(r),read(k);
Q[++tot] = node(l,r,k,2,++qtot);
}
}
qfind(0,1e9,1,tot);
for(int i = 1; i <= qtot; i++)
{
write(ans[i]);
putchar('\n');
}
return 0;
}