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

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[],*p1=buf,*p2=buf;
inline int read()
{
int x = ,f = ;char ch = gtchar();
for(;!isdigit(ch);ch = gtchar())if(ch == '-')f = -f;
for(;isdigit(ch);ch = gtchar())x = * x + ch - '';
return x * f;
}
int n,m;
const int maxn = 2e5 + ;
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 = )
{
int t=,len=; while(t<=x)t*=,len++;
while(len--)t/=,putchar(x/t+),x%=t;
if(opt)putchar(opt);
return;
}
inline void Tarjan(int x,int fa)
{
dfn[x] = low[x] = ++_tim;stk[++top] = x;vis[x] = ;
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] = ;
for(auto targ : Tree[x])
{
if(targ == fa[x])continue;
fa[targ] = x;
dis[targ] = dis[x] + (targ <= n);
dep[targ] = dep[x] + ;
dfs1(targ);
size[x] += size[targ];
}
}
inline void dfs2(int x,int col)
{
int k = ;
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 = ;
tot = n = read();m = read();
for(int i=;i<maxn;i++)G[i].clear(),Tree[i].clear();
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(vis,,sizeof(vis));
for(int i=;i<=m;i++)
{
int u = read(),v = read();
G[u].push_back(v);G[v].push_back(u);
}
for(int i=;i<=n;i++)if(!dfn[i])Tarjan(i,);
int ques = read();_tim = ;dis[] = ;dfs1(),dfs2(,);
while(ques--)
{
int len = read();int k = len,top = ,ans = ;
for(int i=;i<=len;i++)s[i] = read();
sort(s + ,s + len + ,[](int u,int v){return dfn[u] < dfn[v];});
for(int i=;i<k;i++)s[++len] = lca(s[i],s[i + ]);
sort(s + ,s + len + ,[](int u,int v){return dfn[u] < dfn[v];});
len = unique(s + ,s + len + ) - (s + );
if(s[] <= n)ans = ;
else ans = ;
for(int i=;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');
}
}
}

最新文章

  1. 2013 duilib入门简明教程 -- 响应按钮事件(4)
  2. 使用expect scp避免直接输密码
  3. NOI 题库 6264
  4. 在Solr中配置和使用ansj分词
  5. JSON 数组的遍历解析
  6. C/C++ static vs global
  7. (转载)UITableView的详细讲解
  8. Linux常用命令--文件的压缩和解压缩
  9. myeclipse 写java代码提示 dead code 原因
  10. bzoj4038: 医疗援助
  11. C# C/S系统软件开发平台架构图(原创)
  12. hadoop 2.2.0 集群部署 坑
  13. codeforces 340D Bubble Sort Graph(dp,LIS)
  14. Oracle EBS-SQL (BOM-18):检查BOM与工艺路线对照.sql
  15. PyMOTW: heapq¶
  16. 【整理】Java 8新特性总结
  17. raise ValueError(&quot;Cannot convert {0!r} to Excel&quot;.format(value))
  18. 【转载】论文笔记系列-Tree-CNN: A Deep Convolutional Neural Network for Lifelong Learning
  19. scala case类
  20. as3 分发事件无法接收

热门文章

  1. 执行动态的delphi脚本
  2. java的小知识点
  3. APNS推送原理详解
  4. Netty聊天室(2):从0开始实战100w级流量应用
  5. 加密php源代码
  6. react-native 使用 antd-mobile-rn UI进行开发app
  7. JS表单提交
  8. 【题解】Cutting Game
  9. shell基础part3
  10. Android中子线程真的不能更新UI吗?