• Luogu4606 SDOI2018 战略游戏 圆方树、虚树、链并


    传送门


    弱化版

    考虑到去掉一个点使得存在两个点不连通的形式类似割点,不难想到建立圆方树。那么在圆方树上对于给出的关键点建立虚树之后,我们需要求的就是虚树路径上所有圆点的数量减去关键点的数量。

    因为没有DP,所以其实没有必要将虚树建立起来,只需要维护一个链并就可以了。

    #include<bits/stdc++.h>
    //This code is written by Itst
    using namespace std;
    
    inline int read(){
        int a = 0;
        char c = getchar();
        bool f = 0;
        while(!isdigit(c) && c != EOF){
            if(c == '-')
                f = 1;
            c = getchar();
        }
        if(c == EOF)
            exit(0);
        while(isdigit(c)){
            a = a * 10 + c - 48;
            c = getchar();
        }
        return f ? -a : a;
    }
    
    const int MAXN = 2e5 + 7;
    int head[MAXN] , N , M , cnt , cntEd , ans;
    int dfn[MAXN] , low[MAXN] , st[MAXN] , ts , top;
    int ind[MAXN] , dep[MAXN] , TS;
    vector < int > ch[MAXN];
    int num[MAXN] , jump[MAXN][19];
    struct Edge{
        int end , upEd;
    }Ed[MAXN << 1];
    struct cmp{
        bool operator ()(int a , int b){
            return ind[a] < ind[b];
        }
    };
    set < int , cmp > s;
    set < int , cmp > :: iterator it1 , it2;
    
    inline void addEd(int a , int b){
        Ed[++cntEd].end = b;
        Ed[cntEd].upEd = head[a];
        head[a] = cntEd;
    }
    
    void pop(int x , int bot){
        ++cnt;
        ch[cnt].clear();
        ch[x].push_back(cnt);
        do{
            ch[cnt].push_back(st[top]);
        }while(st[top--] != bot);
    }
    
    void tarjan(int x , int p){
        dfn[x] = low[x] = ++ts;
        st[++top] = x;
        ch[x].clear();
        for(int i = head[x] ; i ; i = Ed[i].upEd)
            if(Ed[i].end != p)
                if(!dfn[Ed[i].end]){
                    tarjan(Ed[i].end , x);
                    low[x] = min(low[x] , low[Ed[i].end]);
                    if(low[Ed[i].end] >= dfn[x])
                        pop(x , Ed[i].end);
                }
                else
                    low[x] = min(low[x] , dfn[Ed[i].end]);
    }
    
    void dfs(int x , int p){
        ind[x] = ++TS;
        dep[x] = dep[p] + 1;
        jump[x][0] = p;
        for(int i = 1 ; i <= 18 ; ++i)
            jump[x][i] = jump[jump[x][i - 1]][i - 1];
        num[x] = num[p] + (x <= N);
        for(int i = 0 ; i < ch[x].size() ; ++i)
            dfs(ch[x][i] , x);
    }
    
    inline int LCA(int x , int y){
        if(dep[x] < dep[y])
            swap(x , y);
        for(int i = 18 ; i >= 0 ; --i)
            if(dep[x] - (1 << i) >= dep[y])
                x = jump[x][i];
        if(x == y)
            return x;
        for(int i = 18 ; i >= 0 ; --i)
            if(jump[x][i] != jump[y][i]){
                x = jump[x][i];
                y = jump[y][i];
            }
        return jump[x][0];
    }
    
    inline void insert(int x){
        s.insert(x);
        it1 = it2 = s.find(x);
        int p = 0 , q = 0;
        if(it1 != s.begin())
            p = LCA(*(--it1) , x);
        if(++it2 != s.end())
            q = LCA(*it2 , x);
        p = dep[p] < dep[q] ? q : p;
        ans += num[x] - num[p];
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in","r",stdin);
        freopen("out","w",stdout);
    #endif
        for(int T = read() ; T ; --T){
            cnt = N = read();
            M = read();
            memset(head , 0 , sizeof(head));
            memset(dfn , 0 , sizeof(dfn));
            cntEd = ts = TS = top = 0;
            for(int i = 1 ; i <= M ; ++i){
                int a = read() , b = read();
                addEd(a , b);
                addEd(b , a);
            }
            tarjan(1 , 0);
            dfs(1 , 0);
            for(int Q = read() ; Q ; --Q){
                s.clear();
                ans = 0;
                int S = read() , t;
                for(int i = 1 ; i <= S ; ++i){
                    int a = read();
                    if(i == 1)
                        t = a;
                    else
                        if(t != 1)
                            t = LCA(t , a);
                    insert(a);
                }
                printf("%d
    " , ans - S - num[jump[t][0]]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    PHP实现git部署的方法教程
    windows下php7.1安装redis扩展以及redis测试使用全过程
    win7下php7.1运行getenv('REMOTE_ADDR')fastcgi停止运行
    CGI与FastCGI
    Laravel 单设备登录
    Laravel 登录后清空COOKIE 方法
    PHP进阶与redis锁限制并发访问功能示例
    微信开放平台开发——网页微信扫码登录(OAuth2.0)
    laravel 项目本地版本为5.5,线上mysql 为5.7.21版本,执行严格模式
    mysql中bigint、int、mediumint、smallint与tinyint的取值范围
  • 原文地址:https://www.cnblogs.com/Itst/p/10290442.html
Copyright © 2020-2023  润新知