BZOJ 1015 并查集+离线倒序

统计块个数写错了调了好久啊,BZOJ1696的弱化版本。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <map>
 6 #define fi first
 7 #define se second
 8 #define mp make_pair
 9 #define pa pair<int,int>
10 using namespace std;
11 inline void Get_Int(int &x)
12 {
13     x=0;  char ch=getchar(); int f=1;
14     while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();}
15     while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();} x*=f;
16 }
17 inline void Put_Int(int x)
18 {
19     char ch[20]; int top=0;
20     if (x==0) ch[++top]=‘0‘;
21     while (x) ch[++top]=x%10+‘0‘,x/=10;
22     while (top) putchar(ch[top--]); putchar(‘\n‘);
23 }
24
25 const int Maxn=500200;
26 int father[Maxn],head[Maxn],Ans[Maxn],res,u[Maxn],cnt,v[Maxn],n,m,Q,Pos[Maxn];
27 bool b[Maxn],ret[Maxn];
28 struct Edge{int to,next;}edge[Maxn<<1];
29 int getfather(int x) {if (x==father[x]) return x; return father[x]=getfather(father[x]);}
30 inline void Merge(int u,int v) {father[getfather(u)]=getfather(v);}
31 inline void Add(int u,int v) {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
32 inline void Build()
33 {
34     for (int i=1;i<=n;i++)
35     {
36         if (b[i]) continue;
37         for (int j=head[i];j!=-1;j=edge[j].next) if (!b[edge[j].to]) Merge(i,edge[j].to);
38     }
39 }
40
41 int main()
42 {
43     Get_Int(n),Get_Int(m);
44     for (int i=1;i<=n;i++) father[i]=i;
45     memset(head,-1,sizeof(head)); cnt=0;
46     memset(b,false,sizeof(b));
47     for (int i=1;i<=m;i++) Get_Int(u[i]),Get_Int(v[i]),Add(u[i]+1,v[i]+1),Add(v[i]+1,u[i]+1);
48     Get_Int(Q);
49     for (int i=1;i<=Q;i++) Get_Int(Pos[i]),Pos[i]++,b[Pos[i]]=true;
50     Build();
51     memset(ret,false,sizeof(ret));
52     for (int i=1;i<=n;i++) ret[getfather(i)]=true;
53     int res=0; for (int i=1;i<=n;i++) if (ret[i]) res++;//写成了ret[getfather[i]]了>_<
54     res-=Q;
55     for (int i=Q;i>=1;i--)
56     {
57         Ans[i]=res;
58         b[Pos[i]]=false;
59         for (int j=head[Pos[i]];j!=-1;j=edge[j].next)
60             if (!b[edge[j].to])
61                 if (getfather(Pos[i])!=getfather(edge[j].to)) res--,Merge(Pos[i],edge[j].to);
62         res++;
63     }
64     Ans[0]=res;
65     for (int i=0;i<=Q;i++) Put_Int(Ans[i]);
66     return 0;
67
68 }

C++

时间: 2024-10-23 16:26:31

BZOJ 1015 并查集+离线倒序的相关文章

ACM学习历程—SNNUOJ 1110 传输网络((并查集 &amp;&amp; 离线) || (线段树 &amp;&amp; 时间戳))(2015陕西省大学生程序设计竞赛D题)

Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的.现在他们开始在其他城市陆 续建立了新的基站,命令“C x“代表在城市x建立了一个新的基站,不会在同一个城市建立多个基站:城市编号为1到n,其中城市1就是首都Bytetown.在建立基站的过程中他们还 会询问某个城市的网络信号是从哪个城市传输过来的,命令”Q x“代表查询城市x的来源城市. Inpu

BZOJ 1015 星球大战 并查集+离线

这道题说来真是艰辛,从一开始的RE,到RE,到刚刚的WA,再到AC. 这只能说明我进步的历程,还有我需要不断的加强努力.这道题思路不难,从很久前在黑书中并查集一节就能找到解题的踪影,因为并查集只能并,分不了,所以我们就得离线,倒过来写.只不过这道题真的得审好题目,它问的是剩下的星球中有多少个连通分量,不要搞错了.大概就是这个样子了,加油. 1 #include<cstdio> 2 #include<iostream> 3 #define rep(i,j,k) for(int i=

zoj 3261 Connections in Galaxy War(并查集+离线逆向操作)

 题目:给出一些点,每个点有权值,然后有一些边,相连.无向的.然后有一些操作 query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大) destory a,b 表示删除连接a,b的边 思路并查集,但是要逆向处理,所以先离线读入,从后向前处理,于是对于destroy操作,等价于连接两个点的操作,然后对于每个询问输出即可 #include<cstdio> #include<cstring> #include<cmath> #i

hdu5441(并查集+离线处理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5441 题意: 根据输入的三个整数n.m.q,表示有n座城市,m条路,q次询问.下面给出m行,每行三个数start.end.w,分别是这条道路的起点城市.终点城市."权值".然后给出q次询问的数值,每次询问的结果是符合条件的路有多少条.条件就是:如果这条路的权值比给的限制值要小,那么这条路就是可行的.注意就是:对于一条路的添加来说,只要a到b之间有路,那么符合条件的路就会有两条,一条是a到b

hdu 3938 Portal(并查集+离线+kruskal)

搜了题解才把题搞明白.明白之后发现其实题意很清晰,解题思路也很清晰,只是题目表述的很不清晰…… 大意如下—— 给你一个无向图,图中任意两点的距离是两点间所有路径上的某一条边,这条边需要满足两个条件:1. 这条边这两点间某条路径上的最长边:2. 这条边是这两点间所有路径上的最长边中的最短边. 简单来说,假如a到d有两条路径,一条经过b,一条经过d,其中ab = 1, bd = 3, ac = 2, cd = 2,那么abd上的最长边为3,acd上的最长边为2,则ad的距离为2. 如果a, d两点间

bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列

详见vfleaking在discuss里的题解. 收获: 当我们要顺序枚举一个序列,并且跳过某些元素,那么我们可以用并查集将要跳过的元素合并到一起,这样当一长串元素需要跳过时,可以O(1)跳过. 暴力: 1 /************************************************************** 2 Problem: 1171 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1908 ms 7

【bzoj1015】【JSOI2008】【星球大战】【并查集+离线】

Description 非常久曾经.在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器.并攻下了星系中差点儿全部的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,非常快帝国又又一次造出了他的超级武器. 凭借这超级武器的力量.帝国開始有计划地摧毁反抗军占领的星球.因为星球的不断被摧毁,两个星球之间的通讯通道也開始不可靠起来.如今,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的

fzu 2059 并查集+离线处理

题意: There is a array contain N(1<N<=100000) numbers. Now give you M(1<M<10000) query. Every query will be: 1 x : ask longest substring which every number no less than x 2 y x : change the A[y] to x. there are at most change 10 times. For each

计蒜客 444 / xtuoj 1024 京东的物流路径(并查集+离线lca)

题意:一颗树,定义一条路径的权值等于路径的边权之和,需要求这颗树所有路径中权值的最大值 思路: 考虑到路径权值与点权的最值有关,而最值的问题通常可以通过排序就行处理,于是想到先把点权排序. 容易看出如果某条路径的权值是通过某个点算出的最小 ,那么肯定这条路径肯定不会经过权值更小的点,于是有了两种处理思路 1.按点权从小到大删点,对于即将删除的点,比他权值小的点已经被删去了,所以只要在当前状态的森林里找一条最长路径乘以次点权就可以更新答案 2.按点权从大到小加点,显然新加进来的点权值最小,当前树里