zoukankan      html  css  js  c++  java
  • Aizu 2170 Marked Ancestor(并查集变形)

    寻找根节点很容易让人联想到DisjointSet,但是DisjointSet只有合并操作,

    所以询问离线倒着考虑,标记会一个一个消除,这时候就变成合并了。

    因为询问和查询的时间以及标记生效的时间有关,记录下查询时间,在树上记录的标记。(没有做标记的默认为最大询问时间+1,根节点为0

    在Find的时候根据询问的时间进行回答。

    路径压缩会影响到答案吗?并不会,因为压缩的时候,标记一定已经失效了。

    (答案会爆int,这种问题无非就是在路径上做一些改动,类似比如UVA 11987 Almost Union-Find。分开操作,一般都逆序变成合并

    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<stack>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    //#include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5+5;
    int pa[maxn];
    int Mrk[maxn];
    
    int qt[maxn],qv[maxn];
    int Qt;
    int fdst(int x)
    {
        return Mrk[x] < Qt ? x :pa[x] = fdst(pa[x]);
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        int N, Q;
        while(scanf("%d%d",&N,&Q),N){
            for(int i = 2; i <= N; i++){
                scanf("%d",pa+i);
                Mrk[i] = Q+1;
            }
            int c = 0;
            for(int i = 1; i <= Q; i++){
                char op[2];
                int v;
                scanf("%s%d",op,&v);
                if(*op == 'Q'){
                    qt[c] = i;
                    qv[c++] = v;
                }else {
                    Mrk[v] = min(Mrk[v],i);//取最早生效的标记
                }
            }
            long long ans = 0;
            while(c--){
                Qt = qt[c];
                ans += fdst(qv[c]);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    BZOJ 1191 HNOI2006 超级英雄hero
    BZOJ 2442 Usaco2011 Open 修建草坪
    BZOJ 1812 IOI 2005 riv
    OJ 1159 holiday
    BZOJ 1491 NOI 2007 社交网络
    NOIP2014 D1 T3
    BZOJ 2423 HAOI 2010 最长公共子序列
    LCA模板
    NOIP 2015 D1T2信息传递
    数据结构
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4889510.html
Copyright © 2011-2022 走看看