题解

………………………………………………

我莫不是一个智障吧

我把testdata的编号

当成数据组数读进来

我简直有毒

以为哪里写错了自闭了好久

实际上这题很简单,只要愉悦地开个启发式合并,然后每次暴力修改一个点的根缀主席树和倍增lca数组就行

复杂度\(n \log^2 n\)

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define MAXN 80005
#define eps 1e-10
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,M,Q;
int val[MAXN],w[MAXN],cnt,fa[MAXN][20],belong[MAXN],siz[MAXN],dep[MAXN];
struct node {
int sum,lc,rc;
}tr[MAXN * 200];
struct Enode {
int to,next;
}E[MAXN * 2];
int Ncnt,rt[MAXN],sumE,head[MAXN];
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
int getfa(int u) {
return belong[u] == u ? u : belong[u] = getfa(belong[u]);
}
void Insert(const int &x,int &y,int l,int r,int v) {
y = ++Ncnt;
tr[y] = tr[x];
++tr[y].sum;
if(l == r) return;
int mid = (l + r) >> 1;
if(v <= mid) Insert(tr[x].lc,tr[y].lc,l,mid,v);
else Insert(tr[x].rc,tr[y].rc,mid + 1,r,v);
}
void rebuild(int u,int f) {
dep[u] = dep[f] + 1;
Insert(rt[f],rt[u],1,cnt,w[u]);
fa[u][0] = f;
for(int i = 1 ; i <= 18 ; ++i) {
fa[u][i] = fa[fa[u][i - 1]][i - 1];
}
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != f) rebuild(v,u);
}
}
void Init() {
Ncnt = 0;sumE = 0;
memset(fa,0,sizeof(fa));
memset(rt,0,sizeof(rt));
memset(head,0,sizeof(head));
memset(dep,0,sizeof(dep));
read(N);read(M);read(Q);
for(int i = 1 ; i <= N ; ++i) {
read(w[i]);val[i] = w[i];
}
sort(val + 1,val + N + 1);
cnt = unique(val + 1,val + N + 1) - val - 1;
for(int i = 1 ; i <= N ; ++i) {
w[i] = lower_bound(val + 1,val + cnt + 1,w[i]) - val;
}
for(int i = 1 ; i <= N ; ++i) belong[i] = i,siz[i] = 1;
int u,v;
for(int i = 1 ; i <= M ; ++i) {
read(u);read(v);
add(u,v);add(v,u);
siz[getfa(v)] += siz[getfa(u)];
belong[getfa(u)] = getfa(v);
}
for(int i = 1 ; i <= N ; ++i) {
if(i == belong[i]) rebuild(i,0);
}
}
int lca(int u,int v) {
if(dep[u] < dep[v]) swap(u,v);
int l = 18;
while(dep[u] > dep[v]) {
if(dep[fa[u][l]] >= dep[v]) u = fa[u][l];
--l;
}
if(u == v) return u;
l = 18;
while(fa[u][0] != fa[v][0]) {
if(fa[u][l] != fa[v][l]) {
u = fa[u][l];
v = fa[v][l];
}
--l;
}
return fa[u][0];
}
int Query(int u,int v,int f,int k) {
int L = 1,R = cnt;
int t = w[f];
u = rt[u],v = rt[v],f = rt[f];
while(L < R) {
int mid = (L + R) >> 1;
int s = tr[tr[u].lc].sum - tr[tr[f].lc].sum + tr[tr[v].lc].sum - tr[tr[f].lc].sum;
if(t >= L && t <= mid) ++s;
if(s < k) {
k -= s;
L = mid + 1;
u = tr[u].rc;v = tr[v].rc;f = tr[f].rc;
}
else {
R = mid;
u = tr[u].lc;v = tr[v].lc;f = tr[f].lc;
}
}
return L;
}
void Solve() {
char op[5];int x,y,k;
int lastans = 0;
for(int i = 1 ; i <= Q ; ++i) {
scanf("%s",op + 1);
read(x);read(y);
x ^= lastans;y ^= lastans;
if(op[1] == 'L') {
int p = getfa(x),q = getfa(y);
if(siz[p] > siz[q]) {swap(x,y);swap(p,q);}
belong[p] = q;siz[q] += siz[p];
rebuild(x,y);
add(x,y);add(y,x);
}
else {
read(k);
k ^= lastans;
out(lastans = val[Query(x,y,lca(x,y),k)]);enter;
}
//out(i);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int T;
read(T);
Init();
Solve();
}

【BZOJ】3123: [Sdoi2013]森林的更多相关文章

  1. BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]

    3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...

  2. bzoj 3123: [Sdoi2013]森林(45分暴力)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 4184  Solved: 1235[Submit][Status ...

  3. Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...

  4. ●BZOJ 3123 [Sdoi2013]森林

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3123 题解: 主席树,在线,启发式合并 简单版(只有询问操作):[2588: Spoj 10 ...

  5. BZOJ 3123 [SDOI2013] 森林 - 启发式合并 主席树

    Description 给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值,  连接两棵树中的两个点 Solution 对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出 ...

  6. BZOJ 3123 SDOI2013 森林

    首先对于查询操作就是裸的COT QAQ 在树上DFS建出主席树就可以了 对于连接操作,我们发现并没有删除 所以我们可以进行启发式合并,每次将小的树拍扁插入大的树里并重构即可 写完了之后第一个和第二个点 ...

  7. bzoj 3123 [Sdoi2013]森林(主席树,lca,启发式合并)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  8. bzoj 3123 [Sdoi2013]森林(主席树+启发式合并+LCA)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  9. 3123: [Sdoi2013]森林

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3336  Solved: 978[Submit][Status] ...

随机推荐

  1. Spark2.1.0安装

    1.解压安装spark tar zxf spark-2.1.O-bin-2.6.0-CDH5.10.0.tgz 2.修改配置文件 vim /etc/profile export SPARK_HOME= ...

  2. Java 连接 SqlServer工具类

    1.下载 server2008R2驱动jar包 下载jar包 http://www.microsoft.com/zh-cn/download/confirmation.aspx?id=21599 2. ...

  3. 表单之input的样式修改

    修改placeholder字体颜色 html5为input添加了原生的占位符属性placeholder,高级浏览器都支持这个属性,例如: <input type="text" ...

  4. ubuntu14.04 下安装 gsl 科学计算库

    GSL(GNU Scientific Library)作为三大科学计算库之一,除了涵盖基本的线性代数,微分方程,积分,随机数,组合数,方程求根,多项式求根,排序等,还有模拟退火,快速傅里叶变换,小波, ...

  5. 【vim】自动补全 Ctrl+n

    Vim 默认有自动补全的功能.的确这个功能是很基本的,并且可以通过插件来增强,但它也很有帮助.方法很简单. Vim 尝试通过已经输入的单词来预测单词的结尾. 比如当你在同一个文件中第二次输入 &quo ...

  6. linux内核驱动中对字符串的操作【转】

    转自:http://www.360doc.com/content/12/1224/10/3478092_255969530.shtml Linux内核中关于字符串的相关操作,首先包含头文件: #inc ...

  7. GetStockObject 理解

    原文地址:https://www.cnblogs.com/Clingingboy/archive/2013/04/13/3017952.html GetStockObject在图形编程中是常用API之 ...

  8. saltStack的event接口通过mysql数据库接收SaltStack批量管理日志

    event是一个本地的ZeroMQ PUB Interface,event是一个开放的系统,用于发送信息通知salt或其他的操作系统.每个event都有一个标签.事件标签允许快速制定过滤事件.除了标签 ...

  9. 如何在CentOS 7上安装Munin

    在CentOS 7上安装Munin 首先我们需要在我们的系统中添加EPEL仓库. yum install epel-release 步骤2.安装LAMP(Linux,Apache,MariaDB,PH ...

  10. expdp和impdp快速导出导入,不用创建虚拟目录

    expdp 和impdp不用创建虚拟目录:在cmd直接   expdp 用户名/密码 回车 就导出了,(如果提示输入用户名和密码就输入).再将导出的文件放在oracle默认的dpdump文件夹里面,然 ...