您的位置:首页 > 其它

BZOJ 3123: [Sdoi2013]森林

2017-01-10 10:51 295 查看

3123: [Sdoi2013]森林

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 2745 Solved: 808
[Submit][Status][Discuss]

Description

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

inline char nextC(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 nextI(void)
{
register int ret = 0;
register int neg = false;
register int bit = nextC();

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

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

return neg ? -ret : ret;
}

inline bool nextO(void)
{
register char c = nextC();

while (c != 'Q' && c != 'L')
c = nextC();

return c == 'Q';
}

const int siz = 1000005;

int n, m, q;

int val[siz];
int map[siz], tot;

inline void initMap(void)
{
tot = 0;

for (int i = 1; i <= n; ++i)
map[++tot] = val[i];

//    printf("tot = %d\n", tot);
//
//    for (int i = 1; i < tot; ++i)
//        printf("%d ", map[i]);
//    puts("");

using namespace std;

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

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

for (int i = 1; i <= n; ++i)
val[i] = lower_bound(map + 1, map + tot, val[i]) - map;

//    printf("tot = %d\n", tot);
//
//    for (int i = 1; i < tot; ++i)
//        printf("%d ", map[i]);
//    puts("");
}

int edge;
int hd[siz];
int nt[siz];
int to[siz];

inline void initEdge(void)
{
edge = 0;
memset(hd, -1, sizeof(hd));
//    static int sz = sizeof(int);
//    memset(hd, -1, sz * (n + 5));
}

inline void addEdge(int x, int y)
{
nt[edge] = hd[x]; to[edge] = y; hd[x] = edge++;
nt[edge] = hd[y]; to[edge] = x; hd[y] = edge++;
}

int cnt;
int root[siz];
int ls[siz * 20];
int rs[siz * 20];
int sm[siz * 20];

inline void initTree(void)
{
cnt = 0;
memset(root, 0, sizeof(root));
//    static int sz = sizeof(int);
//    memset(root, 0, sz * (n + 5));
}

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

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

//    printf("%d %d %d %d\n", t, l, r, sm[t]);

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 fa[siz][25], dep[siz];

inline void initLCA(void)
{
memset(dep, 0, sizeof(dep));
//    static int sz = sizeof(int);
//    memset(dep, 0, sz * (n + 5));
}

inline int lca(int a, int b)
{
if (dep[a] < dep[b])
a ^= b ^= a ^= b;

for (int i = 24; i >= 0; --i)
if (dep[fa[a][i]] >= dep[b])
a = fa[a][i];

if (a == b)return a;

for (int i = 24; i >= 0; --i)
if (fa[a][i] != fa[b][i])
a = fa[a][i],
b = fa[b][i];

return fa[a][0];
}

int f[siz], g[siz];

inline void initUnion(void)
{
for (int i = 0; i <= n; ++i)
f[i] = i, g[i] = 1;
}

inline int find(int u)
{
static int stk[siz], top = 0;

while (f[u] != u)
stk[++top] = u, u = f[u];

while (top)
f[stk[top--]] = u;

return u;
}

inline void Union(int a, int b)
{
if (!a)return;
if (!b)return;

a = find(a);
b = find(b);

if (a != b)
{
g[b] += g[a];
f[a] = b;
}
}

void dfs(int u, int fr)
{
//    printf("debug: dfs %d %d\n", u, fr);

Union(u, fr);

fa[u][0] = fr;

dep[u] = dep[fr] + 1;

for (int i = 1; i < 25; ++i)
fa[u][i] = fa[fa[u][i - 1]][i - 1];

insert(root[u], root[fr], 1, tot, val[u], 1);

for (int i = hd[u]; ~i; i = nt[i])
if (to[i] != fr)dfs(to[i], u);
}

int queA[siz], queB[siz], tail;

inline void initQue(void)
{
tail = 0;
}

inline void addQue(int a, int b)
{
queA[tail] = root[a];
queB[tail++] = b;
}

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

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

for (int i = 0; i < tail; ++i)
s += sm[ls[queA[i]]] * queB[i];

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

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

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

int ans;

signed main(void)
{
for (int cas = nextI(); cas--; )
{
n = nextI();
m = nextI();
q = nextI();

for (int i = 1; i <= n; ++i)
val[i] = nextI();

initMap();
initEdge();
initTree();
initUnion();

for (int i = 1; i <= m; ++i)
{
int x = nextI();
int y = nextI();
addEdge(x, y);
}

for (int i = 1; i <= n; ++i)
if (g[find(i)] == 1)
dfs(i, 0);

//        puts("debug: prework finished");

for (int i = 1; i <= q; ++i)
{
if (nextO())    // Query
{
int x = nextI() ^ ans;
int y = nextI() ^ ans;
int k = nextI() ^ ans;

int t = lca(x, y);

//                printf("debug: lca %d %d = %d\n", x, y, t);

initQue();

addQue(x, +1);
addQue(y, +1);
addQue(t, -1);
addQue(fa[t][0], -1);

//                for (int i = 0; i < tail; ++i)
//                    printf("que %d %d\n", queA[i], queB[i]);

printf("%d\n", ans = map[query(1, tot, k)]);
}
else    // Link
{
int x = nextI() ^ ans;
int y = nextI() ^ ans;

if (g[find(x)] > g[find(y)])
dfs(y, x);
else
dfs(x, y);
}
}
}
}
/*
1
8 4 8
1 1 2 2 3 3 4 4
4 7
1 8
2 4
2 1
Q 8 7 3
Q 3 5 1
Q 10 0 0
L 5 4
L 3 2
L 0 7
Q 9 2 5
Q 6 1 6
*/


View Code

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