zoukankan      html  css  js  c++  java
  • 【LOJ】#2562. 「SDOI2018」战略游戏

    题解

    圆方树建好之后点是原来的两倍,而st表求lca也要开到点的两倍,所以是四倍
    我并没有开小,然而= =,我的预处理log2,写成了200000,而不是400000
    我是不是折翼啊= =

    很可写,我们对于割点考虑一下圆方树,发现答案就是圆方树上两个圆点之间经过了多少圆点,把圆点拿出来然后建立虚树,统计一下这个点和父亲之间有多少个圆点,建立虚树之后统计一下加入的lca是不是圆点,如果是的话也要把答案+1

    代码

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    //#define ivorysi
    #define pb push_back
    #define MAXN 200005
    #define eps 1e-12
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define mp make_pair
    #define fi first
    #define se second
    #define mo 974711
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 - '0' + c;
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) putchar('-'),x = -x;
        while(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int T;
    int N,M,Q,sumE,head[MAXN],Cnt;
    struct node {
        int to,next;
    }E[MAXN * 4];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    int dfn[MAXN],low[MAXN],idx,sta[MAXN],top,st[MAXN * 2][20],dep[MAXN],cir[MAXN],len[MAXN * 2];
    vector<int> ver[MAXN];
    int MK[MAXN],C,ans;
    void Tarjan(int u,int fa) {
        dfn[u] = low[u] = ++idx;
        sta[++top] = u;
        for(int i = head[u] ; i ; i = E[i].next) {
    		int v = E[i].to;
    		if(dfn[v] && v != fa) {
    		    low[u] = min(dfn[v],low[u]);
    		}
    		else if(v != fa){
    		    Tarjan(v,u);
    		    if(low[v] >= dfn[u]) {
    				++Cnt;
    				ver[u].pb(Cnt);
    				while(1) {
    				    int x = sta[top--];
    				    ver[Cnt].pb(x);
    				    if(x == v) break;
    				}
    		    }
    		    else low[u] = min(low[u],low[v]);
    		}
        }
    }
    int min_dep(int a,int b) {
        return dep[a] < dep[b] ? a : b;
    }
    int lca(int u,int v) {
        u = dfn[u],v = dfn[v];
        if(u > v) swap(u,v);
        int l = len[v - u + 1];
        return min_dep(st[u][l],st[v - (1 << l) + 1][l]);
    }
    void dfs(int u,int fa) {
        dfn[u] = ++idx;
        st[idx][0] = u;
        cir[u] = cir[fa];
        dep[u] = dep[fa] + 1;
        if(u <= N) ++cir[u];
        
        for(auto k : ver[u]) {
    		dfs(k,u);
    		st[++idx][0] = u;
        }
    }
    bool cmp(int a,int b) {
        return dfn[a] < dfn[b];
    }
    int calc(int a,int b) {
        if(dep[a] < dep[b]) swap(a,b);
        return cir[a] - cir[b] - (a <= N);
    }
    void Build_aux() {
        sort(MK + 1,MK + C + 1,cmp);
        top = 0;
        for(int i = 1 ; i <= C ; ++i) {
    		if(!top) sta[++top] = MK[i];
    		else {
    		    int l = lca(sta[top],MK[i]);
    		    while(top && dep[sta[top]] > dep[l]) {
    				if(top == 1 || dep[sta[top - 1]] <= dep[l]) {
    				    ans += calc(sta[top],l);
    				}
    				else {
    				    ans += calc(sta[top],sta[top - 1]);
    				}
    				--top;
    		    }
    		    if(sta[top] != l) {
    				if(l <= N) ++ans;
    				sta[++top] = l;
    		    }
    		    sta[++top] = MK[i];
    		}
        }
        for(int i = top ; i >= 2 ; --i) ans += calc(sta[i],sta[i - 1]);
    }
    void Init() {
        read(N);read(M);
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(head,0,sizeof(head));
        idx = 0;top = 0;sumE = 0;
        
        for(int i = 1 ; i <= 2 * N ; ++i) ver[i].clear();
        Cnt = N;
        int u,v;
        for(int i = 1 ; i <= M ; ++i) {
    	read(u);read(v);add(u,v);add(v,u);
        }
        Tarjan(1,0);
        idx = 0;
        dfs(1,0);
        for(int j = 1 ; j <= 19 ; ++j) {
    	for(int i = 1 ; i <= idx; ++i) {
    	    if(i + (1 << j) - 1 > idx) break;
    	    st[i][j] = min_dep(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);
    	}
        }
    }
    void Solve() {
        read(Q);
        while(Q--) {
    	read(C);
    	for(int i = 1 ; i <= C ; ++i) read(MK[i]);
    	ans = 0;
    	Build_aux();
    	printf("%d
    ",ans);
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("01.in","r",stdin);
    #endif
        for(int i = 2 ; i <= 400000 ; ++i) len[i] = len[i / 2] + 1;
        read(T);
        while(T--) {
    		Init();
    		Solve();
        }
        return 0;
    }
    
  • 相关阅读:
    Beyond_Compare 4.2.3中文版下载及密钥(亲测可用)
    ORA-0131:Insufficient privileges(Oracle授予用户DEBUG权限)
    常见正则表达式
    MySQL导入导出SQL文件(txt文件)
    存储过程(总结)
    怎样优化数据更新、访问量大的数据库(总结)
    索引原理(平衡树数据结构)
    Oracle面试题
    Linux系统没有IP地址
    iwlist/iwconfig/iw命令
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9080917.html
Copyright © 2011-2022 走看看