初始的时候有一个只有n个点的图(n <= 1e5), 现在进行m( m <= 1e5 )次操作

每次操作要么添加一条无向边, 要么询问之前结点u和v最早在哪一次操作的时候连通了

/*
* Author: Gatevin
* Created Time: 2015/11/21 14:02:38
* File Name: Sakura_Chiyo.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-);
typedef long long lint; #define maxn 100010 int top[maxn];
int grandson[maxn];
int dep[maxn];
int siz[maxn];
int belong[maxn];
int father[maxn];
int Q[maxn];
int cnt;
int hson[maxn]; int q, s;
bool vis[maxn];
int T, n, m;
int id[maxn];
int antiID[maxn]; struct Edge
{
int u, v, w, nex;
Edge(int _u, int _v, int _w, int _nex)
{
u = _u, v = _v, w = _w, nex = _nex;
}
Edge(){}
}; int head[maxn];
int tot;
Edge edge[maxn << ];
int w[maxn];
int idx; void add_Edge(int x, int y, int w)
{
edge[++tot] = Edge(x, y, w, head[x]);
head[x] = tot;
} void split(int root)
{
int l = , r = ;
dep[Q[r] = root] = ;
father[root] = -;
w[root] = ;
while(l < r)
{
int x = Q[++l];
if(head[x] == -) continue;
for(int j = head[x]; j + ; j = edge[j].nex)
{
int y = edge[j].v;
if(y == father[x]) continue;
w[y] = edge[j].w;
dep[Q[++r] = y] = dep[x] + ;
father[y] = x;
}
}
for(int i = r ; i ; i--)
{
int x = Q[i], p = -;
siz[x] = ;
if(head[x] == -) continue;
for(int j = head[x]; j + ; j = edge[j].nex)
{
int y = edge[j].v;
if(y == father[x]) continue;
siz[x] += siz[y];
if(p == - || (p > && siz[y] > siz[p]))
p = y;
}
if(p == -)
{
hson[x] = -;
grandson[++cnt] = x;
belong[top[cnt] = x] = cnt;
}
else
{
hson[x] = p;
belong[x] = belong[p];
top[belong[x]] = x;
}
}
//int idx = 0;
//memset(vis, 0, sizeof(vis));
for(int i = r; i; i--)
{
int x = Q[i];
if(vis[x]) continue;
vis[x] = ;
id[x] = ++idx;
antiID[idx] = x;
while(father[x] != - && belong[father[x]] == belong[x] && !vis[father[x]])
{
x = father[x];
id[x] = ++idx;
antiID[idx] = x;
vis[x] = ;
}
}
return;
} #define lson l, mid, rt << 1
#define rson mid + 1, r , rt << 1 | 1
int val[maxn << ]; void pushUp(int rt)
{
val[rt] = max(val[rt << ], val[rt << | ]);
return;
} void build(int l, int r, int rt)
{
if(l == r)
{
val[rt] = w[antiID[l]];
return;
}
int mid = (l + r) >> ;
build(lson);
build(rson);
pushUp(rt);
} void update(int l, int r, int rt, int pos, int value)
{
if(l == r)
{
val[rt] = value;
return;
}
int mid = (l + r) >> ;
if(pos <= mid) update(lson, pos, value);
else update(rson, pos, value);
pushUp(rt);
return;
} int query(int l, int r, int rt, int L, int R)
{
if(l >= L && r <= R)
return val[rt];
int mid = (l + r) >> ;
int ret = ;
if(mid >= L) ret = max(ret, query(lson, L, R));
if(mid + <= R) ret = max(ret, query(rson, L, R));
return ret;
} int answer(int x, int y)
{
int ans= ;
while(top[belong[x]] != top[belong[y]])
{
if(dep[top[belong[x]]] < dep[top[belong[y]]])
swap(x, y);
ans = max(ans, query(, n, , id[x], id[top[belong[x]]]));
x = father[top[belong[x]]];
}
if(x == y) return ans;
if(dep[x] < dep[y]) swap(x, y);
ans = max(ans, query(, n, , id[x], id[hson[y]]));
return ans;
} void change(int x, int w)
{
x <<= ;
int u = edge[x].u, v = edge[x].v;
if(father[u] == v)
update(, n, , id[u], w);
else update(, n, , id[v], w);
return;
} struct Op
{
int type, u, v, fu, fv, edge;
bool add;
Op(int _t, int _u, int _v)
{
type = _t, u = _u, v = _v;
add = false;
}
Op(){}
}; Op op[maxn]; int fa[maxn];
int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int E;//添加的边的次数
void Union(int x, int y, int opid)
{
int fx = find(x);
int fy = find(y);
op[opid].fu = fx, op[opid].fv = fy;
op[opid].add = false;
if(fx != fy)
{
fa[fx] = fy;
op[opid].add = true;
op[opid].edge = ++E;
add_Edge(fx, fy, opid);
add_Edge(fy, fx, opid);
}
} int ans[maxn]; int read()
{
int x = ;
char c;
while(!isdigit(c = getchar())) continue;
x = (x << ) + (x << ) + c - '';
while(isdigit(c = getchar())) x = (x << ) + (x << ) + c - '';
return x;
} int sis[maxn]; int main()
{
//scanf("%d", &T);
T = read();
int cas = ;
while(T--)
{
cas++;
//scanf("%d %d", &n, &m);
n = read(), m = read();
memset(head, -, sizeof(head));
tot = ; E = ;
for(int i = ; i <= n; i++) fa[i] = i;
for(int i = ; i <= m; i++)
{
//scanf("%d %d %d", &op[i].type, &op[i].u, &op[i].v);
op[i].type = read(), op[i].u = read(), op[i].v = read();
if(op[i].type == ) Union(op[i].u, op[i].v, i);
}
idx = ;
memset(vis, , sizeof(vis));
cnt = ;
for(int i = ; i <= n; i++)
{
int fi = find(i);
if(sis[fi] != cas)
{
split(fi);
sis[fi] = cas;
}
}
build(, n, );
for(int i = m; i > ; i--)
{
if(op[i].type == )//query
{
int u = op[i].u, v = op[i].v;
if(find(u) != find(v))//一直就是不连通的
{
ans[i] = -;
continue;
}
ans[i] = answer(op[i].u, op[i].v);
}
else
{
if(op[i].add == false) continue;//这个操作没有造成过添加边的影响
change(op[i].edge, 1e9);
}
}
for(int i = ; i <= m; i++)
if(op[i].type == )
printf("%d\n", ans[i] == 1e9 ? - : ans[i]);
}
return ;
}

Codeforces Gym 100814C Connecting Graph 树剖并查集/LCA并查集的更多相关文章

  1. Gym 100814C Connecting Graph 并查集+LCA

    Description standard input/output Statements Alex is known to be very clever, but Walter does not be ...

  2. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  3. codeforces 701E E. Connecting Universities(树的重心)

    题目链接: E. Connecting Universities time limit per test 3 seconds memory limit per test 256 megabytes i ...

  4. Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)

    题目链接  2016 ACM-ICPC EC-Final Problem G 题意  给定一个无向图.每个点有一种颜色. 现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的 ...

  5. 2018.08.30 NOIP模拟 graph(dfs序/树剖+线段树)

    [描述] 给你一个图,一共有 N 个点,2*N-2 条有向边. 边目录按两部分给出 1. 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点 到达. 2. 接下来的 N ...

  6. 【BZOJ3999】【TJOI2015】旅游 树剖

    题目大意 给你一棵树,有\(n\)个点.有\(q\)个操作,每次要你从\(x\)到\(y\)的路径上选两个点,使得距离\(x\)比较远的点的点权\(-\)距离\(x\)比较近的点的点权最大,然后把这条 ...

  7. SPOJ375Query on a tree I(树剖+线段树)(询问边)

    ιYou are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  8. codeforces gym 100553I

    codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...

  9. POJ3237 Tree(树剖+线段树+lazy标记)

    You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbe ...

随机推荐

  1. 分组 vs 联合

    // 分组 function groupBy(groups) { return groups.reduce((pre, cur) => { pre[cur.groupId] = (pre[cur ...

  2. vue项目如何部署到Tomcat中

    vue项目如何部署到Tomcat中 1,假设你要访问的项目名称为'hms' 2,在Tomcat的webapps下创建hms文件夹, 3,配置config/index.js文件,build: {} 选项 ...

  3. demo-website配置记录

    demo-website环境配置, 主要是下载flask相关的模块: 1. python安装的是2.7版本. 2. pip install flask pip install flask-httpau ...

  4. Jmeter(十一)测试监听

    性能测试监控的主要任务是获取运行状态收集测试结果, 再对测试结果进行分析. 测试结果有事务响应时间,吞吐量及服务器硬件性能 , 数据库性能状态等等. Jmeter对长时间执行测试计划使用的监听器主要是 ...

  5. vue如何实现热更新

    我们都知道,对于node来说,前端vue代码的迭代节奏是很快的,可能一周要迭代几次,但是node的迭代却没那么平凡,可能一周更新一次甚至更久,那么为了node服务的稳定,减少node服务的发布次数,是 ...

  6. 【OpenCV开发】imread和imwrite的类型以及第三个参数关于图片压缩质量等

    本片参考博客:http://blog.csdn.net/poem_qianmo/article/details/20537737 基于OpenCV3.0,与原博客有出入. 在OpenCV1.0时代,基 ...

  7. Win10删除右键菜单快捷键方法

    打开注册表,找到HKEY_CLASSES_ROOT\Directory\Background路径,删除对应的快捷方式即可

  8. flaskurl传参用法

    from flask import Flask,request app = Flask(__name__) @app.route("/") def index(): return ...

  9. lambda得用法

  10. [转帖]预警 | Linux 爆“SACK Panic”远程DoS漏洞,大量主机受影响

    预警 | Linux 爆“SACK Panic”远程DoS漏洞,大量主机受影响   https://cloud.tencent.com/developer/article/1447879 所有的 版本 ...