[BZOJ3514]CodeChef MARCH14 GERALD07加强版(LCT+主席树)

3514: Codechef MARCH14 GERALD07加强版

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 2177  Solved: 834
[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

Sample Output

2

1

3

1

HINT

对于100%的数据,1≤N、M、K≤200,000。

2016.2.26提高时限至60s

Source

By zhonghaoxi

用LCT求出NTR数组,然后主席树在线查询即可,比较简洁巧妙。

http://hzwer.com/4358.html

不过是两个高级数据结构合在一起,而且不是嵌套,理论上很好写。

实际上犯了很多低级错误,而且非常难调,以后一定要慢点写代码。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define lc ch[x][0]
 4 #define rc ch[x][1]
 5 #define rep(i,l,r) for (int i=l; i<=r; i++)
 6 using namespace std;
 7
 8 const int N=400100,K=200100,M=4000100,inf=1000000000;
 9 int n,m,Q,op,l,r,x,u,v,nd,ans,fa[N],ntr[K],root[K];
10 struct E{ int u,v; }e[K];
11 int find(int x){ return (fa[x]==x) ? x : fa[x]=find(fa[x]); }
12
13 struct LCT{
14     int v[N],mn[N],s[N],ch[N][2],f[N],tag[N];
15     bool isroot(int x){ return (!f[x]) || ((ch[f[x]][0]!=x) && (ch[f[x]][1]!=x)); }
16     void rev(int x){ swap(ch[x][0],ch[x][1]); tag[x]^=1; }
17     void push(int x){ if (tag[x]) rev(lc),rev(rc),tag[x]=0; }
18     void pd(int x){ if (!isroot(x)) pd(f[x]); push(x); }
19
20     void upd(int x){
21         mn[x]=x;
22         if (v[mn[lc]]<v[mn[x]]) mn[x]=mn[lc];
23         if (v[mn[rc]]<v[mn[x]]) mn[x]=mn[rc];
24     }
25
26     void rot(int x){
27         int y=f[x],z=f[y],w=ch[y][1]==x;
28         if (!isroot(y)) ch[z][ch[z][1]==y]=x;
29         f[x]=z; f[y]=x; f[ch[x][w^1]]=y;
30         ch[y][w]=ch[x][w^1]; ch[x][w^1]=y; upd(y);
31     }
32
33     void splay(int x){
34         pd(x);
35         while (!isroot(x)){
36             int y=f[x],z=f[y];
37             if (!isroot(y)){ if ((ch[z][0]==y)^(ch[y][0]==x)) rot(x); else rot(y); }
38             rot(x);
39         }
40         upd(x);
41     }
42
43     void access(int x){ for (int y=0; x; y=x,x=f[x]) splay(x),ch[x][1]=y,upd(x); }
44     void mkroot(int x){ access(x); splay(x); rev(x);}
45     void link(int x,int y){ mkroot(x); f[x]=y; }
46     void cut(int x,int y){ mkroot(x); access(y); splay(y); ch[y][0]=f[x]=0; upd(y); }
47     int que(int x,int y){ mkroot(x); access(y); splay(y); return mn[y]; }
48 }T;
49
50 struct S{
51     int ls[M],rs[M],sm[M];
52
53     void ins(int y,int &x,int L,int R,int pos){
54         x=++nd; ls[x]=ls[y]; rs[x]=rs[y]; sm[x]=sm[y]+1;
55         if (L==R) return; int mid=(L+R)>>1;
56         if (pos<=mid) ins(ls[y],ls[x],L,mid,pos); else ins(rs[y],rs[x],mid+1,R,pos);
57     }
58
59     int que(int x,int y,int L,int R,int k){
60         if (R==k){ return sm[y]-sm[x]; }
61         int mid=(L+R)>>1;
62         if (k<=mid) return que(ls[x],ls[y],L,mid,k);
63             else return sm[ls[y]]-sm[ls[x]]+que(rs[x],rs[y],mid+1,R,k);
64     }
65 }S;
66
67 void Kruskal(){
68     int tot=n;
69     rep(i,1,n) fa[i]=i;
70     rep(i,1,m){
71         int u=e[i].u,v=e[i].v,x=find(u),y=find(v);
72         if (u==v) { ntr[i]=i; continue; }
73         if (x==y){
74             int t=T.que(u,v),k=T.v[t];
75             ntr[i]=k; T.cut(e[k].u,t); T.cut(e[k].v,t);
76         }else fa[x]=y;
77         tot++; T.mn[tot]=tot; T.v[tot]=i;
78         T.link(u,tot); T.link(v,tot);
79     }
80     rep(i,1,m) S.ins(root[i-1],root[i],0,m,ntr[i]);
81 }
82
83 void solve(){
84     rep(i,1,Q){
85         scanf("%d%d",&l,&r);
86         if (op) l^=ans,r^=ans;
87         printf("%d\n",ans=n-S.que(root[l-1],root[r],0,m,l-1));
88     }
89 }
90
91 int main(){
92     freopen("bzoj3514.in","r",stdin);
93     freopen("bzoj3514.out","w",stdout);
94     scanf("%d%d%d%d",&n,&m,&Q,&op);
95     T.v[0]=inf; rep(i,1,n) T.mn[i]=i,T.v[i]=inf;
96     rep(i,1,m) scanf("%d%d",&e[i].u,&e[i].v);
97     Kruskal(); solve();
98     return 0;
99 }

b

原文地址:https://www.cnblogs.com/HocRiser/p/8552656.html

时间: 2024-10-05 05:11:57

[BZOJ3514]CodeChef MARCH14 GERALD07加强版(LCT+主席树)的相关文章

BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献, 答案就是N-x. 用LCT维护加边, 可持久化线段树维护询问. O(NlogN) ------------------------------------------------------------------------------------ #include<cstdio> #inc

BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3514 题意概括 N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. N,M,Q<=200000 题解 http://hzwer.com/4358.html 这题hzwer还是写的很好的-- 代码 #include <cstring> #include <cstdio> #include <cstdlib> #include <al

【LCT+主席树】BZOJ3514 Codechef MARCH14 GERALD07加强版

3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2023  Solved: 778[Submit][Status][Discuss] Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密. 接下来M行,代表图中的每条边. 接下来K行,每行两个整

BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

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

GERALD07加强版:lct,主席树,边化点

Description:N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 传送门. lct这么神仙的东西一个题解都不写怎么行??? 神仙思路啊. 其实不是很难但是的确不容易想到. 我们考虑答案是什么. 首先刚开始有n个点分别是联通块,然后你连了一些边使联通块减少了. 怎么减少的呢?就是区间的边的生成树上边的数量.因为如果不是生成树上的边,那么一定与生成树上的边成环了而不会合并联通块. 怎么判断边是不是区间内生成树上的边呢?判断依据就是它有没有和前面的边成环. 那么我

[bzoj3514]: Codechef MARCH14 GERALD07加强版

跪了半天题解才会..TAT http://hzwer.com/4358.html 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=200233<<1; 6 const int inf=1000023333; 7 struct zs{ 8 int u,v; 9 }e[200233]; 10 int ch[max

BZOJ 3514: Codechef MARCH14 GERALD07加强版

3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1356  Solved: 514[Submit][Status][Discuss] Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M行,代表图中的每条边.接下来K行,每行两个整数L

bzoj 3514 Codechef MARCH14 GERALD07加强版 主席树+LCT

题面 题目传送门 解法 思路很妙 参见hzwer的题解 主席树+LCT--真是个毒瘤的组合 时间复杂度:\(O((m+q)\ log\ m)\) 代码 #include <bits/stdc++.h> #define N 400010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y);} template <typename node>

【bzoj3514】 Codechef MARCH14 GERALD07加强版

http://www.lydsy.com/JudgeOnline/problem.php?id=3514 (题目链接) 题意 给出$n$个点$m$条边的无向图,询问保留图中编号在$[l,r]$的边的时候图中的连通块的个数. Solution 将边的编号作为权值用LCT维护一个最大生成树,同时记录一下加入当前边$i$会把哪一条原本在生成树中的边踢掉,记作$ntr[i]$.如果不会踢掉任意一条边,那么$ntr[i]=0$.如果$i$是自环,那么$ntr[i]=i$. 求出$ntr$数组有什么用呢,我