【bzoj1901】Zju2112 Dynamic Rankings
题目描述:
给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。
样例输入:
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
样例输出:
3
6
题解:
序列上的带修改的求区间第k小。树状数组套可持久化线段树。其实主席树的每一次Insert相当于一次线性变化(大雾),然后普通的主席树是按照上一个版本进行的变化,如果要修改的话那就用树状数组来维护这个线性变化,使得修改的复杂度从O(nlogn)降到了O((logn)^2)。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#ifdef CT
#define debug(...) printf(__VA_ARGS__)
#define setfile()
#else
#define debug(...)
#define filename ""
#define setfile() freopen(filename".in","r",stdin);freopen(filename".out","w",stdout);
#endif
#define R register
#define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1<<15],*S=B,*T=B;
inline int FastIn()
{
R char ch;R int cnt=0;R bool minus=0;
while (ch=getc(),(ch < '0' || ch > '9') && ch != '-');
ch == '-' ?minus=1:cnt=ch-'0';
while (ch=getc(),ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus?-cnt:cnt;
}
#define maxt 6200010
#define maxn 10010
const int oo = 1e9;
int root[maxn], sum[maxt], ls[maxt], rs[maxt], tot, lcnt, rcnt, val[maxn], lr[maxn], rr[maxn];
#define lowbit(_x) ((_x) & -(_x))
int update (R int last, R int l, R int r, R int pre,R int c)
{
R int mid = l + r >> 1, nw = ++tot;
sum[nw] = sum[last] + c;
if (l == r) return nw;
if (pre > mid)
{
ls[nw] = ls[last];
rs[nw] = update(rs[last], mid + 1, r, pre, c);
}
else
{
rs[nw] = rs[last];
ls[nw] = update(ls[last], l, mid, pre, c);
}
return nw;
}
inline int query(R int l, R int r, R int k)
{
while (l < r)
{
R int lsum = 0, rsum = 0, mid = l + r >> 1;
for (R int i = 1; i <= lcnt; ++i)
lsum += sum[ls[lr[i]]];
for (R int i = 1; i <= rcnt; ++i)
rsum += sum[ls[rr[i]]];
if (rsum - lsum >= k)
{
for (R int i = 1; i <= lcnt; ++i)
lr[i] = ls[lr[i]];
for (R int i = 1; i <= rcnt; ++i)
rr[i] = ls[rr[i]];
r = mid;
}
else
{
for (R int i = 1; i <= lcnt; ++i)
lr[i] = rs[lr[i]];
for (R int i = 1; i <= rcnt; ++i)
rr[i] = rs[rr[i]];
l = mid + 1;
k -= (rsum - lsum);
}
}
return l;
}
int main()
{
// setfile();
R int n = FastIn(), q = FastIn();
for (R int i = 1; i <= n; ++i)
{
R int a = FastIn();
for (R int j = i; j <= n; j += lowbit(j))
root[j] = update(root[j], 0, oo, a, 1);
val[i] = a;
}
for (R int i = 1; i <= q; ++i)
{
R char cmd = getc();
while (cmd!='Q'&&cmd!='C') cmd = getc();
R int a = FastIn(), b = FastIn();
if (cmd == 'Q')
{
R int k = FastIn();
lcnt = rcnt = 0;
for (R int j = a - 1; j; j -= lowbit(j))
lr[++lcnt] = root[j];
for (R int j = b; j; j -= lowbit(j))
rr[++rcnt] = root[j];
printf("%d\n",query(0, oo, k) );
}
else
{
for (R int j = a; j <= n; j += lowbit(j))
root[j] = update(root[j], 0, oo, val[a], -1);
val[a] = b;
for (R int j = a; j <= n; j += lowbit(j))
root[j] = update(root[j], 0, oo, b, 1);
}
}
return 0;
}

浙公网安备 33010602011771号