Marked Ancestor
一道并查集的题目硬是被我当成线段树写了,感觉这样写虽然不是最好的,不过能a就行
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103906#problem/G
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2170
首先题意:
一个可以被标记的树,起初只有根节点被标记了,然后有两种操作,第一种操作是把某一个点标记,第二个操作是询问他的祖先中离他最近的节点编号,最后出书询问的节点编号和.
这是我在并查集专题上面遇到的,不过第一反应暴力肯定不行(然而暴力的并查集查找祖先也可以过...),然后想半天没思路,因为当前节点的询问过后不能直接路径压缩,因为这样后面如果该条路径有一个点被标记那就gg了
但此时想法是如果这个点被标记了,那么他的后代可能都会受到影响,但是又不能一个一个去更新影响,想到这里再加上题目中的两种操作更新查询和线段树神似,所以就开始搞线段树,但是这里有一个问题:线段树更新的点都在一起...,接着想到以前一道没做出来的题(翻硬币类似的)用了dfsn重建树然后再更新维护,所以就用先序遍历了一下,同时我记录下了每个节点的深度,因为更新的时候,深度更深的点应该把深度浅的点信息更新掉(为啥?举一个抽象例子,如果点A被B和C更新了,那么肯定B和C是A的祖先,如果depB<depC,那么depC离A更近)
其他的都是细节问题了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <map>
#include <queue>
#include <vector> using namespace std;
const int maxn = 1e5+100;
const int INF = 0x3f3f3f3f;
#define pr(x) // cout << #x << " = " << x << " ";
#define prln(x) // cout << #x << " = " << x <<endl;
#define ll long long
int head[maxn], nxt[maxn], to[maxn], dfsn, cnt, id[maxn], r[maxn], _n, sum[maxn<<2], dep[maxn];
//建最初的树
void addedge(int u, int v) {
nxt[cnt] = head[u];
head[u] = cnt;
to[cnt++] = v;
}
//线段树等初始化
void init(int n) {
cnt = dfsn = 0;
_n = 1;
while(_n < n) _n = _n*2;
int _nn = _n*2;
for(int i = 0; i <= _nn; ++i) sum[i] = -1;
for(int i = 0; i <= n;++i) {
head[i] =-1;
}
}
//dfs建树
//这里保证了一个点的后代都在一起被访问到,最左边的点是这个点id[u]表示最左边点//的编号,r[u]表示u后代最右边点编号
void dfstree(int fa,int u) {
id[u] = ++dfsn;
dep[u] = dep[fa]+1;
for(int i = head[u]; ~i; i = nxt[i]){
dfstree(u,to[i]);
}
r[u] = dfsn;
}
//这里是线段树的更新操作
//sum初始化为-1,如果当前未被更新或者更新的点深度小于v2这个点深度,,那么更新
inline void getans(int& ans, const int& v2){
if(ans == -1 || dep[ans] < dep[v2]) ans = v2;
}
//其他和正常线段树都一样了
void pushdown(int rt) {
if(sum[rt] != -1) {
getans(sum[rt<<1], sum[rt]);
getans(sum[rt<<1|1],sum[rt]);
}
}
void update(int rt, int l, int r, int ql, int qr, int v) {
if(ql <= l && r <= qr) {
getans(sum[rt], v);
return;
}
pushdown(rt);
int m = l + r >> 1;
if(m >= ql) update(rt<<1, l, m, ql, qr, v);
if(m < qr) update(rt<<1|1, m+1, r, ql, qr, v);
}
//这里查询稍微改了一下,直接向上找
int query(int rt) {
rt += _n-1;
int ans = 0;
while(rt>=1) {
getans(ans,sum[rt]);
rt = rt>>1;
}
return ans;
}
int main(){
#ifdef LOCAL
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
//freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
int n, m, x;
char op[10];
while(cin >> n >> m && (n||m)) {
ll ans = 0;
init(n);
for(int i = 2; i <= n; ++i) {
scanf("%d", &x);
addedge(x,i);
}
dep[0] = 0;
dfstree(0,1);
update(1, 1, _n, id[1], r[1], 1);
for(int i = 0; i < m; ++i) {
scanf("%s%d", op, &x);
if(op[0] == 'M') update(1, 1, _n, id[x], r[x], x);
else ans += query(id[x]);
}
printf("%lld\n", ans);
}
return 0;
}
Marked Ancestor的更多相关文章
- AOJ 2170 Marked Ancestor (基础并查集)
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=45522 给定一棵树的n个节点,每个节点标号在1到n之间,1是树的根节点,有如 ...
- Aizu 2170 Marked Ancestor
题意:出一颗树,有两种操作:1. mark u 标记结点u2.query u 询问离u最近的且被标记的祖先结点是哪个让你输出所有询问的和. 思路:数据量太小,直接暴力dfs就可以了 #incl ...
- Marked Ancestor [AOJ2170] [并查集]
题意: 有一个树,有些节点染色,每次有两种操作,第一,统计该节点到离它最近的染色父亲结点的的号码(Q),第二,为某一个节点染色(M),求第一种操作和. 输入: 输入由多个数据集组成.每个数据集都有以下 ...
- Aizu2170 Marked Ancestor(并查集)
https://vjudge.net/problem/Aizu-2170 并查集用于管理元素分组情况. 建树pre[]记录父节点,一开始只有结点1被标记了,所以find()最终得到的根都是1. 如果遇 ...
- AOJ 2170 Marked Ancestor[并查集][离线]
题意: 给你一颗N个节点的树,节点编号1到N.1总是节点的根.现在有两种操作: M v: 标记节点v Q v: 求出离v最近的标记的相邻节点.根节点一开始就标记好了. 现在给一系列操作,求出所有Q操作 ...
- Aizu 2170 Marked Ancestor(并查集变形)
寻找根节点很容易让人联想到DisjointSet,但是DisjointSet只有合并操作, 所以询问离线倒着考虑,标记会一个一个消除,这时候就变成合并了. 因为询问和查询的时间以及标记生效的时间有关, ...
- Aizu:2170-Marked Ancestor
Marked Ancestor Time limit 8000 ms Memory limit 131072 kB Problem Description You are given a tree T ...
- ProgrammingContestChallengeBook
POJ 1852 Ants POJ 2386 Lake Counting POJ 1979 Red and Black AOJ 0118 Property Distribution AOJ 0333 ...
- mysq l错误Table ‘./mysql/proc’ is marked as crashed and should be repaired
续上一篇,解决了上一篇中的问题后,启动成功,但是在数据库中操作会存在一些问题,一些操作报一下异常: Table './mysql/proc' is marked as crashed and shou ...
随机推荐
- idea 导出可以直接运行的jar 文件
刚开始采用的maven插件是 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId ...
- Canvas + WebSocket + Redis 实现一个视频弹幕
原文出自:https://www.pandashen.com 页面布局 首先,我们需要实现页面布局,在根目录创建 index.html 布局中我们需要有一个 video 多媒体标签引入我们的本地视频, ...
- python设置图片背景和设置字体颜色大小
# -*- coding: utf-8 -*- """ Created on Wed Dec 11 22:37:30 2019 @author: Dell "& ...
- N皇后问题 --使用位运算解决
关键位运算 x & (-x) 取得最低位1 x & (x-1) 去掉最低位1 class Solution(object): def totalNQueens(self, n): &q ...
- sqlserver 返回刚插入的那条数据
insert into xxxxxx(Col_002,UrgentStatus,DoWorkShop,Col_004,Col_005,Col_006,Col_003,Col_007,postQQ,Co ...
- 【java工具类】下载文件
FileUtil.java /** * 下载文件 * @param file; * @param response */ public static void downloadFile(File fi ...
- [BZOJ4011][HNOI2015]落忆枫音:拓扑排序+容斥原理
分析 又是一个有故事的题目背景.作为玩过原作的人,看题目背景都快看哭了ToT.强烈安利本境系列,话说SP-time的新作要咕到什么时候啊. 好像扯远了嘛不管了. 一句话题意就是求一个DAG再加上一条有 ...
- 2018-2019-2-20175225 实验三 《敏捷开发与XP实践》实验报告
一.实验内容与步骤 1.安装.使用alibaba插件规范代码 - 在IDEA的setting中找到plugins并搜索alibaba,点击install进行安装 - 重启IDEA后,在代码中右击点击编 ...
- hg(Mercurial)使用参考
hg(Mercurial)使用参考 使用hg(mercurial)有好几个月了,个人感觉这款分布式的版本控制系统非常不错,易学,易用:你可以从做在你旁边的同事拉取完整的代码; 对网络的依赖性更低, ...
- 代码测试:unsigned char*图像数据转换成OpenCV中Mat类型
直接使用Mat的构造函数,把指针的位置赋给下面中的data就OK了: Mat(int rows, int cols, int type, void* data, size_t step=AUTO_ST ...