题目链接:https://cn.vjudge.net/problem/ZOJ-3261

题意

有n个星星,之间有m条边

现一边询问与x星连通的最大星的编号,一边拆开一些边

思路

一开始是真不会,甚至想用dfs模拟

最后查了一下,这个题原来是要离线操作,拆边就变为合并

这很为难哈哈,本以为有个什么更好的数据结构(动态树?)

存边我们用一个set<int>来存一个数字即可(bfs这类写多了就很容易考虑到压缩数据

还有一个重要的点,就是并查集的join可以用来维护一个最大(小)数据作为跟节点的值

代码

#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=10000, maxq=50000;
struct IdxMap{
int val, idx;
IdxMap(int val=0, int idx=0):
val(val), idx(idx) {}
bool operator < (const IdxMap &a) const{
if (val!=a.val) return val>a.val;
return idx<a.idx;
}
}imap[maxn+5];
struct Operate{
// true for destory(add)
bool ifadd; int a, b;
Operate(bool ifadd=false, int a=-1, int b=-1):
ifadd(ifadd), a(a), b(b) {}
}operate[maxq+5];
struct Node{
int pre, data;// rank, data;
Node(int pre=0, int data=0):// int rank=0, int data=0):
pre(pre), data(data) {}// rank(rank), data(data) {}
}node[maxn+5];
int n, m, q, asize=0, ans[maxq+5];
set<int> edge; // smeller proir int find(int x){
return (node[x].pre==x)?x:(node[x].pre=find(node[x].pre));
} void join(int a, int b){
a=find(a); b=find(b);
if (a==b) return;
// if (node[a].rank==node[b].rank) node[a].rank++;
if (node[a].data>=node[b].data) node[b].pre=a;
else node[a].pre=b;
} inline int getcode(const int &a, const int &b){
if (a<b) return a*maxn+b;
return b*maxn+a;
} int findBiggest(int x){
// int &val=node[x].data;
// for (int i=0; i<n; i++){
// if (val>=imap[i].val) return -1;
// if (find(x)==find(imap[i].idx)) return imap[i].idx;
// }return -1;
int root=find(x);
if (node[root].data>node[x].data) return root;
return -1;
} int main(void){
int first=true;
while(scanf("%d", &n)==1 && n){
edge.clear();
asize=0; for (int i=0, tmp; i<n; i++){
scanf("%d", &tmp);
imap[i]=IdxMap(tmp, i);
node[i]=Node(i, tmp);
}sort(imap, imap+n);
scanf("%d", &m);
for (int i=0, a, b; i<m; i++){
scanf("%d%d", &a, &b);
edge.insert(getcode(a, b));
} char str[25];
scanf("%d", &q);
for (int i=0, a, b; i<q; i++){
scanf("%s", str);
if (str[0]=='d'){
scanf("%d%d", &a, &b);
operate[i]=Operate(true, a, b);
edge.erase(getcode(a, b));
}else if (str[0]=='q'){
scanf("%d", &a);
operate[i]=Operate(false, a, -1);
}
} for (set<int>::iterator it=edge.begin(); it!=edge.end(); it++)
join((*it)/maxn, (*it)%maxn); for (int i=q-1; i>=0; i--){
if (operate[i].ifadd) join(operate[i].a, operate[i].b);
else ans[asize++]=findBiggest(operate[i].a);
}
if (!first) printf("\n");
else first=false;
for (int i=asize-1; i>=0; i--) printf("%d\n", ans[i]);
} return 0;
}
Time Memory Length Lang Submitted
260ms 2124kB 2764 C++ (g++ 4.7.2) 2018-03-20 23:26:36

> 18-03-21 Update:并查集维护最值

ZOJ-3261 Connections in Galaxy War 并查集 离线操作的更多相关文章

  1. 洛谷 P1197 BZOJ 1015 [JSOI2008]星球大战 (ZOJ 3261 Connections in Galaxy War)

    这两道题长得差不多,都有分裂集合的操作,都是先将所有操作离线,然后从最后一步开始倒着模拟,这样一来,分裂就变成合并,也就是从打击以后最终的零散状态,一步步合并,回到最开始所有星球都被连为一个整体的状态 ...

  2. ZOJ 3261 - Connections in Galaxy War ,并查集删边

    In order to strengthen the defense ability, many stars in galaxy allied together and built many bidi ...

  3. 题解报告:zoj 3261 Connections in Galaxy War(离线并查集)

    Description In order to strengthen the defense ability, many stars in galaxy allied together and bui ...

  4. zoj 3261 Connections in Galaxy War(并查集逆向加边)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261 题意:有很多颗星球,各自有武力值,星球间有一些联系通道,现 ...

  5. ZOJ 3261 Connections in Galaxy War(逆向并查集)

    参考链接: http://www.cppblog.com/yuan1028/archive/2011/02/13/139990.html http://blog.csdn.net/roney_win/ ...

  6. ZOJ 3261 Connections in Galaxy War (逆向+带权并查集)

    题意:有N个星球,每个星球有自己的武力值.星球之间有M条无向边,连通的两个点可以相互呼叫支援,前提是对方的武力值要大于自己.当武力值最大的伙伴有多个时,选择编号最小的.有Q次操作,destroy为切断 ...

  7. zoj 3261 Connections in Galaxy War

    点击打开链接zoj 3261 思路: 带权并查集 分析: 1 题目说的是有n个星球0~n-1,每个星球都有一个战斗值.n个星球之间有一些联系,并且n个星球之间会有互相伤害 2 根本没有思路的题,看了网 ...

  8. ZOJ - 3261 Connections in Galaxy War(并查集删边)

    https://cn.vjudge.net/problem/ZOJ-3261 题意 银河系各大星球之间有不同的能量值, 并且他们之间互相有通道连接起来,可以用来传递信息,这样一旦有星球被怪兽攻击,便可 ...

  9. ZOJ3261 Connections in Galaxy War 并查集

    分析:对于这种删边操作,我们通常可以先读进来,然后转化离线进行倒着加边 #include <stdio.h> #include <string.h> #include < ...

随机推荐

  1. MySQL学习(六)——自定义连接池

    1.连接池概念 用池来管理Connection,这样可以重复使用Connection.有了池,我们就不用自己来创建Connection,而是通过池来获取Connection对象.当使用完Connect ...

  2. 哪位大兄弟有用 cMake 开发Android ndk的

    一直用 Android studio 开发ndk,但是gradle支持的不是很好,只有experimental 版本支持 配置各种蛋疼.主要每次新建一个module都要修改配置半天.之前也看到过goo ...

  3. Html标记语言学习一2017年6月12日

    今天主要学习了 frame的用法. <frameset> 可以将网页分成几个不同的部分 使用 cols  和  rows 两种标记.前者是列,后者是行 <frame/>  单标 ...

  4. luogu P1622 释放囚犯

    题目描述 Caima王国中有一个奇怪的监狱,这个监狱一共有P个牢房,这些牢房一字排开,第i个紧挨着第i+1个(最后一个除外).现在正好牢房是满的. 上级下发了一个释放名单,要求每天释放名单上的一个人. ...

  5. python编写登录与注册

    #编写简单的注册与登陆模块 #使用死循环来检测 while True: #如果条件为真,则一直循环 sum=3 #定义密码输入的次数 username = input("请输入用户名:&qu ...

  6. vmware vsphere出现“需要整合虚拟机磁盘”的告警处理方法(完整版)

    vmware vsphere出现“需要整合虚拟机磁盘”的告警 处理步骤: 1.选择对应虚机,快照——整合 (不行看下一条) 通常情况执行完第一步就好了 2.如果整合报错,提示文件锁定 2.1 新建快照 ...

  7. 解决wps的ppt演示不能打开的问题libbz2.so.1.0

      安装 wps-office-10.1.0.5707-1.a21.x86_64 无法打开ppt 其他正常

  8. HNU 13101 The Triangle Division of the Convex Polygon 组合数的因式分解求法

    题意: 求第n-2个Catalan数 模上 m. 思路: Catalan数公式: Catalan[n] = C(n, 2n)/(n+1) = (2n)!/[(n+1)!n!] 因为m是在输入中给的,所 ...

  9. [Angular] Configure an Angular App at Compile Time with the Angular CLI

    Compile time configuration options allow you to provide different kind of settings based on the envi ...

  10. mysql-组合查询

    一.组合查询 mysql允许执行多个查询(多条select语句),并将结果作为单个查询结果集返回.这些组合查询通常称为并(union)或复合查询(compound query). 有两种情况需要使用组 ...