您的位置:首页 > 其它

BZOJ 1901: Zju2112 Dynamic Rankings

2017-01-09 08:35 465 查看

1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 7294 Solved: 3039
[Submit][Status][Discuss]

Description

给定一个含有n个数的序列a[1],a[2],a[3]……a
,程序必须回答这样的询问:对于给定的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
,这些数都小于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。

Input

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

Output

Sample Input

5 3

3 2 1 4 7

Q 1 4 3

C 2 6

Q 2 5 3

Sample Output

3

6

HINT

20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

Source

[Submit][Status][Discuss]

带修主席树(树状数组+主席树) 模板题

#include <bits/stdc++.h>

inline char nextChar(void)
{
static const int siz = 1024;

static char buf[siz];
static char *hd = buf + siz;
static char *tl = buf + siz;

if (hd == tl)
fread(hd = buf, 1, siz, stdin);

return *hd++;
}

inline int nextInt(void)
{
register int ret = 0;
register int neg = false;
register int bit = nextChar();

for (; bit < 48; bit = nextChar())
if (bit == '-')neg ^= true;

for (; bit > 47; bit = nextChar())
ret = ret * 10 + bit - 48;

return neg ? -ret : ret;
}

inline int nextOrd(void)
{
register int bit = nextChar();

while (bit != 'Q' && bit != 'C')
bit = nextChar();

return bit == 'Q';
}

const int siz = 40005;

struct data
{
int k, a, b, c;
}s[siz];

int n, m, num[siz];

int map[siz], tot = 0;

inline int find(int x)
{
return std::lower_bound(map + 1, map + tot, x) - map;
}

inline void makeMap(void)
{
for (int i = 1; i <= n; ++i)
map[++tot] = num[i];

for (int i = 1; i <= m; ++i)
if (!s[i].k)map[++tot] = s[i].b;

std::sort(map + 1, map + tot + 1);

tot = std::unique(map + 1, map + tot + 1) - map;

for (int i = 1; i <= n; ++i)
num[i] = find(num[i]);

for (int i = 1; i <= m; ++i)
if (!s[i].k)s[i].b = find(s[i].b);
}

int ls[siz * 200];
int rs[siz * 200];
int sz[siz * 200];

void insert(int &t, int f, int l, int r, int p, int v)
{
static int cnt = 0;

t = ++cnt;

ls[t] = ls[f];
rs[t] = rs[f];
sz[t] = sz[f] + v;

if (l != r)
{
int mid = (l + r) >> 1;

if (p <= mid)
insert(ls[t], ls[f], l, mid, p, v);
else
insert(rs[t], rs[f], mid + 1, r, p, v);
}
}

int root[siz];

inline void insert(int t, int p, int v)
{
for (; t <= tot; t += t&-t)
insert(root[t], root[t], 1, tot, p, v);
}

int node[siz], tims[siz], tail;

inline void push(int t, int k)
{
for (; t >= 1; t -= t&-t)
{
node[tail] = root[t];
tims[tail++] = k;
}
}

int query(int l, int r, int k)
{
if (l == r)return l;

int sum = 0, mid = (l + r) >> 1;

for (int i = 0; i < tail; ++i)
sum += tims[i] * sz[ls[node[i]]];

if (sum >= k)
{
for (int i = 0; i < tail; ++i)
node[i] = ls[node[i]];

return query(l, mid, k);
}
else
{
for (int i = 0; i < tail; ++i)
node[i] = rs[node[i]];

return query(mid + 1, r, k - sum);
}
}

signed main(void)
{
n = nextInt();
m = nextInt();

for (int i = 1; i <= n; ++i)
num[i] = nextInt();

for (int i = 1; i <= m; ++i)
{
if (s[i].k = nextOrd())
{
s[i].a = nextInt();
s[i].b = nextInt();
s[i].c = nextInt();
}
else
{
s[i].a = nextInt();
s[i].b = nextInt();
}
}

makeMap();

for (int i = 1; i <= n; ++i)
insert(i, num[i], 1);

for (int i = 1; i <= m; ++i)
{
if (s[i].k)
{
tail = 0;
push(s[i].b, 1);
push(s[i].a - 1, -1);
printf("%d\n", map[query(1, tot, s[i].c)]);
}
else
{
insert(s[i].a, num[s[i].a], -1);
num[s[i].a] = s[i].b;
insert(s[i].a, num[s[i].a], 1);
}
}
}


@Author: YouSiki
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: