您的位置:首页 > 其它

【BZOJ2733】[HNOI2012]永无乡【启发式合并】【Splay】

2016-05-23 07:48 357 查看
【题目链接】

合并时候启发式合并就可以了。

注意第9个点第99999个合并操作连接了0 0...调了好长时间= =

/* Telekinetic Forest Guard */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 100005;

int n, m;

int son[maxn][2], pre[maxn], val[maxn], size[maxn];

inline int iread() {
int f = 1, x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return f * x;
}

inline void pushup(int x) {
size[x] = size[son[x][0]] + 1 + size[son[x][1]];
}

inline void rotate(int x) {
int y = pre[x], z = pre[y], type = son[y][1] == x;
pre[son[y][type] = son[x][!type]] = y;
pre[x] = z;
if(z) son[z][son[z][1] == y] = x;
pre[son[x][!type] = y] = x;
pushup(y); pushup(x);
}

inline void splay(int x, int goal) {
while(pre[x] != goal) {
int y = pre[x], z = pre[y];
if(z == goal) rotate(x);
else if(son[z][1] == y ^ son[y][1] == x) rotate(x), rotate(x);
else rotate(y), rotate(x);
}
}

inline int findroot(int x) {
splay(x, 0);
for(; son[x][0]; x = son[x][0]);
return x;
}

inline int find(int x, int k) {
while(k != size[son[x][0]] + 1)
if(k <= size[son[x][0]]) x = son[x][0];
else k -= size[son[x][0]] + 1, x = son[x][1];
return x;
}

inline void insert(int x, int y) {
for(size[y]++; son[y][val[x] > val[y]]; y = son[y][val[x] > val[y]], size[y]++);
pre[son[y][val[x] > val[y]] = x] = y;
size[x] = 1;
splay(x, 0);
}

inline void trash(int x, int y) {
if(!x) return;
trash(son[x][0], y);
trash(son[x][1], y);
son[x][0] = son[x][1] = size[x] = pre[x] = 0;
insert(x, y);
}

inline void link(int u, int v) {
if(findroot(u) == findroot(v)) return;
splay(u, 0); splay(v, 0);
if(size[u] > size[v]) swap(u, v);
trash(u, v);
}

inline int query(int x, int k) {
splay(x, 0);
if(k > size[x]) return -1;
return find(x, k);
}

int main() {
n = iread(); m = iread();
for(int i = 1; i <= n; i++) val[i] = iread(), size[i] = 1;
for(int i = 1; i <= m; i++) {
int u = iread(), v = iread();
if(!u && !v) continue;
link(u, v);
}
for(m = iread(); m; m--) {
char ch = getchar(); for(; ch != 'B' && ch != 'Q'; ch = getchar());
int x = iread(), y = iread();
if(ch == 'B') link(x, y);
else printf("%d\n", query(x, y));
}
return 0;
}


附暴力
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;

const int maxn = 100002;

struct data {
int w, id;

bool operator < (const data &x) const {
return w != x.w ? w < x.w : id < x.id;
}
};

int n, m, fa[maxn];
set<data> s[maxn];

inline int iread() {
int f = 1, x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return f * x;
}

inline int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}

inline void link(int u, int v) {
if(find(u) == find(v)) return;
u = find(u); v = find(v);
if(s[u].size() > s[v].size()) swap(u, v);
for(set<data>::iterator it = s[u].begin(); it != s[u].end(); it++)
s[v].insert(*it);
s[u].clear();
fa[u] = v;
}

inline int query(int x, int k) {
x = find(x);
if(k > s[x].size()) return -1;
set<data>::iterator it = s[x].begin();
for(k--; k; it++, k--);
return (*it).id;
}

int main() {
n = iread(); m = iread();
for(int i = 1; i <= n; i++) s[i].insert((data){iread(), i}), fa[i] = i;
for(int i = 1; i <= m; i++) {
int u = iread(), v = iread();
link(u, v);
}
for(m = iread(); m; m--) {
char ch = getchar(); for(; ch != 'B' && ch != 'Q'; ch = getchar());
int x = iread(), y = iread();
if(ch == 'B') link(x, y);
else printf("%d\n", query(x, y));
}
return 0;
}


mk
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>

using namespace std;

const int maxn = 100005;

int n, m, fa[maxn], val[maxn];

inline int rd(int x) {
return rand() % x + 1;
}

inline int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}

int main() {
srand(time(0));

int n = 100000, m = rd(n + 1) - 1;
printf("%d %d\n", n, m);
for(int i = 1; i <= n; i++) {
fa[i] = i;
val[i] = i;
int x = rd(i);
swap(val[i], val[x]);
}
for(int i = 1; i <= n; i++) printf("%d ", val[i]);
printf("\n");
for(int i = 1; i <= m; i++) {
int x = rd(n), y = rd(n);
for(; x == y; y = rd(n));
printf("%d %d\n", x, y);
}
m = 300000;
printf("%d\n", m);
for(int i = 1; i <= m; i++) {
int opt = rd(2), x = rd(n), y = rd(n);
if(opt == 1) {
for(; x == y; y = rd(n));
printf("B %d %d\n", x, y);
} else {
printf("Q %d %d\n", x, y);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: