bzoj3514:Codechef MARCH14 GERALD07加强版 关于一类LCT维护动态图的连通性问题
来源:互联网 发布:hadoop 数据挖掘 编辑:程序博客网 时间:2024/06/05 21:49
3514: Codechef MARCH14 GERALD07加强版
Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1900 Solved: 721
[Submit][Status][Discuss]
Description
N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。
Input
第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。
接下来M行,代表图中的每条边。
接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。
Output
K行每行一个整数代表该组询问的联通块个数。
Sample Input
3 5 4 0
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2
Sample Output
2
1
3
1
1
3
1
HINT
对于100%的数据,1≤N、M、K≤200,000。
2016.2.26提高时限至60s
Source
By zhonghaoxi
这是一道关于LCT维护动态图的连通性问题。
先说做法:
1.先将每条边加入图中,然后如果这条边所在两个点已经构成了环,那么把这个环中最早加入的一条边,并把这条边记录为当前边的前驱。early[i]=j
2.那么对于l~r区间的每天边,我们需要的答案就是n-(∑[early[i]<l==1](l<=i<=r))也及n-(l~r中pre小于等于l的边的个数)
About正确性:如果要是early[i]<l说明这条边一定连接了两个连通块,因此这条边减少了一个连同块,对答案的贡献是-1。否则它对答案没有贡献。
维护?:对于1.可以用LCT,对于一条边记其边权是其加入时间戳。然后边权转点权,用LCT维护最小值节点即可。对于2.可以用主席树,查询区间小于某个数的个数即可。
#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<algorithm>#include<map>#include<cmath>#define maxn 440000#define maxt 4400000#define ls ch[p][0]#define rs ch[p][1]#define inf 0x3f3f3f3fusing namespace std;int read() { char ch = getchar(); int x = 0, f = 1; while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9') {x = x * 10 - '0' + ch; ch = getchar();} return x * f;} int ch[maxn][2], fa[maxn], mn[maxn], val[maxn];bool rev[maxn];int root[maxn], sum[maxt], lc[maxt], rc[maxt], sz;int n, m, Q, type, top, st[maxn], early[maxn], eu[maxn], ev[maxn];bool wh(int p) {return ch[fa[p]][1] == p;}bool Isroot(int p) {return ch[fa[p]][0] != p && ch[fa[p]][1] != p;} void update(int p) { mn[p] = p; if(val[mn[p]] > val[mn[ls]]) mn[p] = mn[ls]; if(val[mn[p]] > val[mn[rs]]) mn[p] = mn[rs];}void push_down(int p) { if(rev[p]) { rev[ls] ^= 1; rev[rs] ^= 1; rev[p] ^= 1; swap(ls, rs); }} void push_up(int p) { st[top = 1] = p; for(int i = p; !Isroot(i); i = fa[i]) st[++top] = fa[i]; for(int i = top; i; --i) push_down(st[i]);} void Rotate(int p) { int f = fa[p], g = fa[f], c = wh(p); if(!Isroot(f)) ch[g][wh(f)] = p; fa[p] = g; ch[f][c] = ch[p][c ^ 1]; if(ch[f][c]) fa[ch[f][c]] = f; ch[p][c ^ 1] = f; fa[f] = p; update(f);} void Splay(int p) { push_up(p); for(; !Isroot(p); Rotate(p)) if(!Isroot(fa[p])) Rotate(wh(fa[p]) == wh(p) ? fa[p] : p); update(p);} void Access(int p) { for(int pre = 0; p; pre = p, p = fa[p]) { Splay(p); rs = pre; update(p); }} void makeroot(int p) {Access(p); Splay(p); rev[p] ^= 1;}void Link(int p, int g) { makeroot(p); fa[p] = g;} void Cut(int p, int g) { makeroot(p); Access(g); Splay(g); fa[p] = ch[g][0] = 0;} int Query(int u, int v) { makeroot(u); Access(v); Splay(v); return mn[v];}int find(int p) {Access(p); Splay(p); while(ls) p = ls; return p;} void add(int L, int R, int pre_p, int &cur_p, int val) { sum[cur_p = ++sz] = sum[pre_p] + 1; if(L == R) return; int mid = L + R >> 1; if(val <= mid) { rc[cur_p] = rc[pre_p]; add(L, mid, lc[pre_p], lc[cur_p], val); } else { lc[cur_p] = lc[pre_p]; add(mid + 1, R, rc[pre_p], rc[cur_p], val); }} void LCT() { int tot = n; for(int i = 1;i <= m; ++i) { int u = read(), v = read(); eu[i] = u; ev[i] = v; if(u == v) {early[i] = i;continue;} if(find(u) == find(v)) { int t = Query(u, v); early[i] = val[t]; Cut(eu[early[i]], t); Cut(ev[early[i]], t); } ++tot; mn[tot] = tot; val[tot] = i; Link(u, tot); Link(v, tot); } //for(int i = 1; i <= m; ++i) cout<<early[i]<<" "; //cout<<endl; for(int i = 1;i <= m; ++i) add(0, m, root[i - 1], root[i], early[i]);} int query(int L, int R, int lt, int rt, int val) { if(R == val) return sum[rt] - sum[lt]; int mid = L + R >> 1; if(val <= mid) return query(L, mid, lc[lt], lc[rt], val); else return sum[lc[rt]] - sum[lc[lt]] + query(mid + 1, R, rc[lt], rc[rt], val); } void PST() { int lastans = 0; while(Q--) { int l = read(), r = read(); if(type) l ^= lastans, r ^= lastans; lastans = n - query(0, m, root[l - 1], root[r], l - 1); printf("%d\n", lastans); }} int main(){ n = read(); m = read(); Q = read(); type = read(); val[0] = inf; for(int i = 1;i <= n; ++i) mn[i] = i, val[i] = inf; LCT(); PST(); return 0;}
阅读全文
0 0
- bzoj3514:Codechef MARCH14 GERALD07加强版 关于一类LCT维护动态图的连通性问题
- bzoj3514 Codechef MARCH14 GERALD07加强版 LCT&&主席树
- Bzoj3514:Codechef MARCH14 GERALD07加强版:LCT+主席树
- 【bzoj3514】【Codechef MARCH14 GERALD07加强版】【lct+主席树】
- 【BZOJ3514】Codechef MARCH14 GERALD07加强版,LCT+主席树
- [LCT && 主席树] BZOJ3514 .Codechef MARCH14 GERALD07 加强版
- bzoj3514: Codechef MARCH14 GERALD07加强版
- BZOJ3514: Codechef MARCH14 GERALD07加强版
- 【BZOJ3514】Codechef MARCH14 GERALD07加强版
- BZOJ3514: Codechef MARCH14 GERALD07加强版
- [BZOJ3514]Codechef MARCH14 GERALD07加强版
- [bzoj3514] Codechef MARCH14 GERALD07加强版
- 【bzoj3514】Codechef MARCH14 GERALD07加强版
- BZOJ3514:Codechef MARCH14 GERALD07加强版 (LCT+可持久化线段树)
- BZOJ 3514 Codechef MARCH14 GERALD07加强版 LCT+主席树
- 【LCT】【bzoj 3514】: Codechef MARCH14 GERALD07加强版
- BZOJ 3514 Codechef MARCH14 GERALD07加强版 LCT+主席树
- 【 bzoj 3514 】Codechef MARCH14 GERALD07加强版 - LCT
- CSS-字体属性
- 多项式轨迹--直线和抛物线轨迹
- 初识RDBMS与SQL
- freemarker标签使用及配置
- 剑指offer——面试题41:和为s 的两个数字
- bzoj3514:Codechef MARCH14 GERALD07加强版 关于一类LCT维护动态图的连通性问题
- dcom配置
- CodeForces
- main函数与命令行参数
- 课堂展示
- Kafka+Spark Streaming+Redis实时计算整合实践
- linux插入模式命令行模式,底行模式,gcc和makefile指令
- 学生管理系统设计(数据库版)
- AI人才缺失催生的“跨境猎头”,人才年薪高达300万,猎头直赚100万