Dynamic Rankings代码
主要是记录一下整体二分的板子
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAXN 100000
struct element {//修改
int loc;
int time;//时间戳
int value;
int com;
element (){}
element (int loc1, int time1, int value1, int com1) {
loc = loc1;
time = time1;
value = value1;
com = com1;
}
}se[MAXN * 3 + 5], teme[MAXN * 3 + 5];
int End = 0;
struct question {//询问
int num;
int l, r;
int k;
int time;//时间戳
question (){}
question (int num1, int l1, int r1, int k1, int time1) {
num = num1;
l = l1;
r = r1;
k = k1;
time = time1;
}
}sq[MAXN + 5], temq[MAXN + 5];
int num = 0;
bool vis[MAXN + 5];
int BIT[MAXN + 5];//单点修改, 区间查询通过BIT来实现
int snow[MAXN + 5];//每次修改需要先删除这个位置上一次的值, 再添加新的值, 所以用一个数组存
int answer[MAXN + 5];//答案
int lowbit (int i) {
return i & (-i);
}
void change (int l, int v) {
for (int i = l; i <= MAXN; i += lowbit (i)) {
BIT[i] += v;
}
}
int Sum (int l){
int ans = 0;
for (int i = l; i; i ^= lowbit (i)) {
ans += BIT[i];
}
return ans;
}
int ask (int l, int r) {
return Sum (r) - Sum (l - 1);
}
void dichotomy (int le, int re, int lq, int rq, int vl, int vr) {
if (vl == vr) {//如果二分到底了, 就直接是答案了
for (int i = lq; i <= rq; i ++) {
answer[sq[i].num] = vl;
}
return ;
}
int mid = (vl + vr) >> 1;
int ie = le, iq = lq;
for (int i = lq; i <= rq; i ++) {//相当于普通二分中check的0, 1
vis[i] = 0;
}
while (ie <= re && iq <= rq) {
if (se[ie].time <= sq[iq].time) {//时间戳来判断操作先后
change (se[ie].loc, (se[ie].value <= mid) * se[ie].com);
ie ++;
}
else {
int sum = ask (sq[iq].l, sq[iq].r);
vis[iq] = (sum >= sq[iq].k);
if (!vis[iq]) {
sq[iq].k -= sum;//分到mid右边后要将左边修改的贡献提前算上好
}
iq ++;
}
}
while (iq <= rq) {
int sum = ask (sq[iq].l, sq[iq].r);
vis[iq] = (sum >= sq[iq].k);
if (!vis[iq]) {
sq[iq].k -= sum;
}
iq ++;
}
for (int i = le; i < ie; i ++) {//将BIT清0
change (se[i].loc, -(se[i].value <= mid) * se[i].com);
}
//将询问和修改都按照mid分为左右两边
int ne = le - 1;
for (int i = le; i <= re; i ++) {
if (se[i].value <= mid) {
teme[++ ne] = se[i];
}
}
for (int i = le, j = ne; i <= re; i ++) {
if (se[i].value > mid) {
teme[++ j] = se[i];
}
}
for (int i = le; i <= re; i ++) {
se[i] = teme[i];
}
int nq = lq - 1;
for (int i = lq; i <= rq; i ++) {
if (vis[i]) {
temq[++ nq] = sq[i];
}
}
for (int i = lq, j = nq; i <= rq; i ++) {
if (!vis[i]) {
temq[++ j] = sq[i];
}
}
for (int i = lq; i <= rq; i ++) {
sq[i] = temq[i];
}
if (nq >= lq) {
dichotomy (le, ne, lq, nq, vl, mid);
}
if (nq < rq) {
dichotomy (ne + 1, re, nq + 1, rq, mid + 1, vr);
}
}
int main () {
int n, m;
scanf ("%d %d", &n, &m);
for (int i = 1; i <= n; i ++) {
scanf ("%d", &snow[i]);
se[++End] = element (i, 0, snow[i], 1);
}
for (int i = 1; i <= m; i ++) {
char opt = getchar ();
while (opt > 'Z' || opt < 'A') {
opt = getchar ();
}
if (opt == 'Q') {
int l, r, k;
scanf ("%d %d %d", &l, &r, &k);
++num;
sq[num] = question (num, l, r, k, i);
}
else if (opt == 'C') {
int l;
int v;
scanf ("%d %d", &l, &v);
se[++End] = element (l, i, snow[l], -1);
snow[l] = v;
se[++End] = element (l, i, snow[l], 1);
}
};
dichotomy (1, End, 1, num, 0, 1e9);
for (int i = 1; i <= num; i ++) {
printf ("%d\n", answer[i]);
}
}

浙公网安备 33010602011771号