一道并查集的题目硬是被我当成线段树写了,感觉这样写虽然不是最好的,不过能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更近)

其他的都是细节问题了

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <string>
  6. #include <queue>
  7. #include <cstdlib>
  8. #include <algorithm>
  9. #include <stack>
  10. #include <map>
  11. #include <queue>
  12. #include <vector>
  13.  
  14. using namespace std;
  15. const int maxn = 1e5+100;
  16. const int INF = 0x3f3f3f3f;
  17. #define pr(x) // cout << #x << " = " << x << " ";
  18. #define prln(x) // cout << #x << " = " << x <<endl;
  19. #define ll long long
  20. int head[maxn], nxt[maxn], to[maxn], dfsn, cnt, id[maxn], r[maxn], _n, sum[maxn<<2], dep[maxn];
  1. //建最初的树
  2. void addedge(int u, int v) {
  3. nxt[cnt] = head[u];
  4. head[u] = cnt;
  5. to[cnt++] = v;
  6. }
  1. //线段树等初始化
  2. void init(int n) {
  3. cnt = dfsn = 0;
  4. _n = 1;
  5. while(_n < n) _n = _n*2;
  6. int _nn = _n*2;
  7. for(int i = 0; i <= _nn; ++i) sum[i] = -1;
  8. for(int i = 0; i <= n;++i) {
  9. head[i] =-1;
  10. }
  11. }
  12. //dfs建树
  1. //这里保证了一个点的后代都在一起被访问到,最左边的点是这个点id[u]表示最左边点//的编号,r[u]表示u后代最右边点编号
  2. void dfstree(int fa,int u) {
  3. id[u] = ++dfsn;
  4. dep[u] = dep[fa]+1;
  5. for(int i = head[u]; ~i; i = nxt[i]){
  6. dfstree(u,to[i]);
  7. }
  8. r[u] = dfsn;
  9. }
  1. //这里是线段树的更新操作
  1. //sum初始化为-1,如果当前未被更新或者更新的点深度小于v2这个点深度,,那么更新
  2. inline void getans(int& ans, const int& v2){
  3. if(ans == -1 || dep[ans] < dep[v2]) ans = v2;
  4. }
  1. //其他和正常线段树都一样了
  2. void pushdown(int rt) {
  3. if(sum[rt] != -1) {
  4. getans(sum[rt<<1], sum[rt]);
  5. getans(sum[rt<<1|1],sum[rt]);
  6. }
  7. }
  8. void update(int rt, int l, int r, int ql, int qr, int v) {
  9. if(ql <= l && r <= qr) {
  10. getans(sum[rt], v);
  11. return;
  12. }
  13. pushdown(rt);
  14. int m = l + r >> 1;
  15. if(m >= ql) update(rt<<1, l, m, ql, qr, v);
  16. if(m < qr) update(rt<<1|1, m+1, r, ql, qr, v);
  17. }
  1. //这里查询稍微改了一下,直接向上找
  1. int query(int rt) {
  2. rt += _n-1;
  3. int ans = 0;
  4. while(rt>=1) {
  5. getans(ans,sum[rt]);
  6. rt = rt>>1;
  7. }
  8. return ans;
  9. }
  10. int main(){
  11. #ifdef LOCAL
  12. freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
  13. //freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
  14. #endif
  15. int n, m, x;
  16. char op[10];
  17. while(cin >> n >> m && (n||m)) {
  18. ll ans = 0;
  19. init(n);
  20. for(int i = 2; i <= n; ++i) {
  21. scanf("%d", &x);
  22. addedge(x,i);
  23. }
  24. dep[0] = 0;
  25. dfstree(0,1);
  26. update(1, 1, _n, id[1], r[1], 1);
  27. for(int i = 0; i < m; ++i) {
  28. scanf("%s%d", op, &x);
  29. if(op[0] == 'M') update(1, 1, _n, id[x], r[x], x);
  30. else ans += query(id[x]);
  31. }
  32. printf("%lld\n", ans);
  33. }
  34. return 0;
  35. }

Marked Ancestor的更多相关文章

  1. AOJ 2170 Marked Ancestor (基础并查集)

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=45522 给定一棵树的n个节点,每个节点标号在1到n之间,1是树的根节点,有如 ...

  2. Aizu 2170 Marked Ancestor

    题意:出一颗树,有两种操作:1. mark  u  标记结点u2.query  u  询问离u最近的且被标记的祖先结点是哪个让你输出所有询问的和. 思路:数据量太小,直接暴力dfs就可以了 #incl ...

  3. Marked Ancestor [AOJ2170] [并查集]

    题意: 有一个树,有些节点染色,每次有两种操作,第一,统计该节点到离它最近的染色父亲结点的的号码(Q),第二,为某一个节点染色(M),求第一种操作和. 输入: 输入由多个数据集组成.每个数据集都有以下 ...

  4. Aizu2170 Marked Ancestor(并查集)

    https://vjudge.net/problem/Aizu-2170 并查集用于管理元素分组情况. 建树pre[]记录父节点,一开始只有结点1被标记了,所以find()最终得到的根都是1. 如果遇 ...

  5. AOJ 2170 Marked Ancestor[并查集][离线]

    题意: 给你一颗N个节点的树,节点编号1到N.1总是节点的根.现在有两种操作: M v: 标记节点v Q v: 求出离v最近的标记的相邻节点.根节点一开始就标记好了. 现在给一系列操作,求出所有Q操作 ...

  6. Aizu 2170 Marked Ancestor(并查集变形)

    寻找根节点很容易让人联想到DisjointSet,但是DisjointSet只有合并操作, 所以询问离线倒着考虑,标记会一个一个消除,这时候就变成合并了. 因为询问和查询的时间以及标记生效的时间有关, ...

  7. Aizu:2170-Marked Ancestor

    Marked Ancestor Time limit 8000 ms Memory limit 131072 kB Problem Description You are given a tree T ...

  8. ProgrammingContestChallengeBook

    POJ 1852 Ants POJ 2386 Lake Counting POJ 1979 Red and Black AOJ 0118 Property Distribution AOJ 0333 ...

  9. mysq l错误Table ‘./mysql/proc’ is marked as crashed and should be repaired

    续上一篇,解决了上一篇中的问题后,启动成功,但是在数据库中操作会存在一些问题,一些操作报一下异常: Table './mysql/proc' is marked as crashed and shou ...

随机推荐

  1. .NET界面控件DevExpress全新发布v19.1.4|更改DCT解码器

    DevExpress Universal Subscription(又名DevExpress宇宙版或DXperience Universal Suite)是全球使用广泛的.NET用户界面控件套包,De ...

  2. Tronado【第1篇】:tronado的简单使用以及使用

    Tronado Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp ...

  3. 对GraphQL-BFF:微服务背景下的前后端数据交互方案的研究-------引用

    随着多终端.多平台.多业务形态.多技术选型等各方面的发展,前后端的数据交互,日益复杂. 同一份数据,可能以多种不同的形态和结构,在多种场景下被消费. 在理想情况下,这些复杂性可以全部由后端承担.前端只 ...

  4. shiro框架学习-8-shiro缓存

    1. shiro进行认证授权时会查询数据库获取用户角色权限信息,每次登录都会去查询,这样对性能会又影响.可以设置缓存,查询时先去缓存中查找,缓存中没有再去数据库查询. 从shiro的架构图中可以看到有 ...

  5. [转] 数值优化(Numerical Optimization)学习系列-目录

    from:https://blog.csdn.net/fangqingan_java/article/details/48951191 概述数值优化对于最优化问题提供了一种迭代算法思路,通过迭代逐渐接 ...

  6. [luogu]P1800 software_NOI导刊2010提高(06)[DP][二分答案]

    [luogu]P1800 software_NOI导刊2010提高(06) 题目描述 一个软件开发公司同时要开发两个软件,并且要同时交付给用户,现在公司为了尽快完成这一任务,将每个软件划分成m个模块, ...

  7. OI多项式 简单学习笔记

    咕咕咕 先开个坑(其实是存模板来了) 一些特别简单的前置东西qwq 复数的计算 复数相加:向量相加,复数相乘.复数相乘:模长相乘,旋转量相加(就是复平面坐标轴逆时针旋转的角度) (当然也可以直接使用c ...

  8. (69)Python异常处理与断言

    http://blog.csdn.net/pipisorry/article/details/21841883 断言 断言是一句必须等价于布尔真的判定;此外,发生异常也意味着表达式为假.这些工作类似于 ...

  9. Hive函数介绍

    一些函数不太会,查了些资料,分享一下 Hive已定义函数介绍: 1.字符串长度函数:length 语法: length(string A)返回值: int举例:[sql] view plain cop ...

  10. 修改docker下mysql配置

    1.在/home/smile/docker/mysql/config/目录下增加一个文件 my.cnf # Copyright (c) , Oracle and/or its affiliates. ...