bzoj5329 战略游戏

有一个圆方树,每次给出一个点集,询问虚树上圆点数量-询问点数量

sol:题意读懂就很简单了...可以建虚树dp

也可以考虑每一条链对答案的贡献,最后要注意单独计算虚树根对答案的贡献

#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC target("avx")
#include<bits/stdc++.h>
#define LL long long
using namespace std;
#define gtchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
static char buf[1000000],*p1=buf,*p2=buf;
inline int read()
{
    int x = 0,f = 1;char ch = gtchar();
    for(;!isdigit(ch);ch = gtchar())if(ch == '-')f = -f;
    for(;isdigit(ch);ch = gtchar())x = 10 * x + ch - '0';
    return x * f;
}
int n,m;
const int maxn = 2e5 + 10;
vector<int> G[maxn],Tree[maxn];
int dfn[maxn],low[maxn],_tim,stk[maxn],top,vis[maxn];
int tot;
inline void write(int x,char opt = 0)
{
    int t=10,len=1; while(t<=x)t*=10,len++;
    while(len--)t/=10,putchar(x/t+48),x%=t;
    if(opt)putchar(opt);
    return;
}
inline void Tarjan(int x,int fa)
{
    dfn[x] = low[x] = ++_tim;stk[++top] = x;vis[x] = 1;
    for(auto targ : G[x])
    {
        if(targ == fa)continue;
        if(!vis[targ])
        {
            Tarjan(targ,x);
            low[x] = min(low[x],low[targ]);
            if(low[targ] >= dfn[x])
            {
                tot++;
                Tree[x].push_back(tot);
                do
                {
                    Tree[tot].push_back(stk[top]);
                }while(targ != stk[top--]);
            }
        }
        else low[x] = min(low[x],dfn[targ]);
    }
}
int s[maxn];
int fa[maxn],dep[maxn],size[maxn],bl[maxn],dis[maxn];
inline void dfs1(int x)
{
    size[x] = 1;
    for(auto targ : Tree[x])
    {
        if(targ == fa[x])continue;
        fa[targ] = x;
        dis[targ] = dis[x] + (targ <= n);
        dep[targ] = dep[x] + 1;
        dfs1(targ);
        size[x] += size[targ];
    }
}
inline void dfs2(int x,int col)
{
    int k = 0;
    bl[x] = col;dfn[x] = ++_tim;
    for(auto targ : Tree[x])
        if(dep[targ] > dep[x] && size[targ] > size[k])k = targ;
    if(!k){low[x] = _tim;return;}
    dfs2(k,col);
    for(auto targ : Tree[x])
        if(dep[targ] > dep[x] && targ != k)dfs2(targ,targ);
    low[x] = _tim;
}
inline int lca(int x,int y)
{
    while(bl[x] != bl[y])
    {
        if(dep[bl[x]] < dep[bl[y]])swap(x,y);
        x = fa[bl[x]];
    }
    return dep[x] < dep[y] ? x : y;
}
int q[maxn];
int main()
{
    int T = read();
    while(T--)
    {
        _tim = 0;
        tot = n = read();m = read();
        for(int i=1;i<maxn;i++)G[i].clear(),Tree[i].clear();
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=m;i++)
        {
            int u = read(),v = read();
            G[u].push_back(v);G[v].push_back(u);
        }
        for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i,0);
        int ques = read();_tim = 0;dis[1] = 1;dfs1(1),dfs2(1,1);
        while(ques--)
        {
            int len = read();int k = len,top = 0,ans = 0;
            for(int i=1;i<=len;i++)s[i] = read();
            sort(s + 1,s + len + 1,[](int u,int v){return dfn[u] < dfn[v];});
            for(int i=1;i<k;i++)s[++len] = lca(s[i],s[i + 1]);
            sort(s + 1,s + len + 1,[](int u,int v){return dfn[u] < dfn[v];});
            len = unique(s + 1,s + len + 1) - (s + 1);
            if(s[1] <= n)ans = 1;
            else ans = 0;
            for(int i=1;i<=len;i++)
            {
                while(top && low[q[top]] < dfn[s[i]])top--;
                if(top)ans += (dis[s[i]] - dis[q[top]]);
                q[++top] = s[i];
            }
            write(ans - k,'\n');
        }
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/Kong-Ruo/p/9768405.html