[CC-ADJLEAF2]Adjacent Leaves

题目大意:

给定一棵有根树,考虑从根开始进行DFS,将所有叶子按照被遍历到的顺序排列得到一个序列。

定义一个叶子集合合法,当且仅当存在一种DFS的方式使得这个叶子集合在序列中的出现位置是一个连续子串。

给出一个\(n(n\le5\times10^5)\)个点的无根树,\(m(m\le5\times10^5)\)次询问,求以\(R\)为根的情况下叶子集合\(S(\sum|S|\le5\times10^5)\)是否合法。

思路:

定义\(leaf[x]\)为以\(x\)为根的子树内叶子结点的个数,\(cnt[x]\)为以\(x\)为根的子树内属于\(S\)的点的个数。

定义以\(x\)为根的子树是“不满的”,当且仅当\(cnt[x]\ne0\)且\(cnt[x]\ne leaf[x]\)。

对于一个结点\(x\),若其有\(\ge3\)个子树是不满的,或其有\(2\)个子树不满,且\(cnt[x]\ne|S|\),则\(S\)不合法。

对于每次询问,用一次\(\mathcal O(n)\)的树形DP求解,我们就得到了一个\(\mathcal O(nm)\)的做法。

由于\(\sum|S|\le5\times10^5\),我们可以建立虚树,将每次DFS的点数缩小为\(|S|\),此时一次DP的时间复杂度为\(\mathcal O(|S|\log n)\),总时间复杂度\(\mathcal O(\sum|S|\log n)\)。

源代码:

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=5e5+1,logN=19;
std::vector<int> e[N],node;
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
int r,dep[N],anc[N][logN],dfn[N],s[N],leaf[N],tot;
inline int lg2(const float &x) {
return ((unsigned&)x>>23&255)-127;
}
void dfs(const int &x,const int &par) {
anc[x][0]=par;
dfn[x]=++tot;
dep[x]=dep[par]+1;
leaf[x]=e[x].size()==1;
for(register int i=1;i<=lg2(dep[x]);i++) {
anc[x][i]=anc[anc[x][i-1]][i-1];
}
for(auto &y:e[x]) {
if(y==par) continue;
dfs(y,x);
leaf[x]+=leaf[y];
}
}
inline int lca(int x,int y) {
if(dep[x]<dep[y]) std::swap(x,y);
for(register int i=lg2(dep[x]-dep[y]);i>=0;i--) {
if(dep[anc[x][i]]>=dep[y]) {
x=anc[x][i];
}
}
for(register int i=lg2(dep[x]);i>=0;i--) {
if(anc[x][i]!=anc[y][i]) {
x=anc[x][i];
y=anc[y][i];
}
}
return x==y?x:anc[x][0];
}
inline bool is_anc(const int &x,int y) {
//x shi y de zuxian
if(dep[x]>dep[y]) return false;
for(register int i=lg2(dep[y]-dep[x]);i>=0;i--) {
if(dep[anc[y][i]]>=dep[x]) {
y=anc[y][i];
}
}
return x==y;
}
inline int jump(int x,const int &d) {
//zhaodao x shendu wei d de zuxian
for(register int i=lg2(dep[x]-d);i>=0;i--) {
if(dep[anc[x][i]]>=d) {
x=anc[x][i];
}
}
return x;
}
inline int near_ch(const int &x,const int &y) {
//zhaodao x zuijin de zijiedian, bingqie shi y de zuxian
if(is_anc(x,y)) {
return jump(y,dep[x]+1);
} else {
return anc[x][0];
}
}
inline int count_leaves(const int &x) {
if(x==r) return leaf[1];
if(is_anc(x,r)) {
return leaf[1]-leaf[jump(r,dep[x]+1)];
} else {
return leaf[x];
}
}
class AuxTree {
//auxiliary tree
private:
int stk[N],top,cnt[N];
std::vector<int> e[N];
void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
public:
void build(int s[],const int &r) {
const int n=s[0]+1;
s[n]=r;
std::sort(&s[1],&s[n]+1,
[](const int &i,const int &j) {
return dfn[i]<dfn[j];
}
);
stk[top=1]=s[1];
node.push_back(s[1]);
for(register int i=2;i<=n;i++) {
const int &x=s[i],p=lca(x,stk[top]);
while(dfn[p]<dfn[stk[top]]) {
if(dfn[p]>=dfn[stk[top-1]]) {
add_edge(p,stk[top--]);
if(stk[top]!=p) {
stk[++top]=p;
node.push_back(p);
}
break;
} else {
add_edge(stk[top],stk[top-1]);
top--;
}
}
stk[++top]=x;
node.push_back(x);
}
for(;top>1;top--) {
add_edge(stk[top],stk[top-1]);
}
}
void dfs(const int &x,const int &par) {
int tmp=0;
cnt[x]=x!=r&&e[x].size()==1;
for(auto &y:e[x]) {
if(y==par) continue;
dfs(y,x);
cnt[x]+=cnt[y];
tmp+=cnt[y]<count_leaves(near_ch(x,y));
}
if(tmp>2||(tmp==2&&cnt[x]!=s[0])) throw 0;
}
void clear() {
for(auto &x:node) {
e[x].clear();
}
node.clear();
}
};
AuxTree t;
int main() {
const int n=getint(),m=getint();
for(register int i=1;i<n;i++) {
add_edge(getint(),getint());
}
dfs(1,0);
for(register int i=0;i<m;i++) {
r=getint();
for(register int i=0;i<=s[0];i++) {
s[i]=getint();
}
t.build(s,r);
try {
t.dfs(r,0);
puts("YES");
} catch(...) {
puts("NO");
}
t.clear();
}
return 0;
}

[CC-ADJLEAF2]Adjacent Leaves的更多相关文章

  1. TOJ 4008 The Leaf Eaters(容斥定理)

    Description As we all know caterpillars love to eat leaves. Usually, a caterpillar sits on leaf, eat ...

  2. TOJ 4008 The Leaf Eaters

    |A∪B∪C|=|A|+|B|+|C|-|A∩B|-|A∩C|-|B∩C|+|A∩B∩C| 这个是集合的容斥,交集差集什么的,这个在概率论经常用到吧 4008: The Leaf Eaters   T ...

  3. Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)

     http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何 ...

  4. 03-树2 List Leaves

    二叉树及其遍历 一遍AC,挺开心的hhh~ 简单讲下思路:叶子,顾名思义就是没有左右子树的结点.由于题目要求,叶子结点的输出顺序是从上往下,从左往右.所以用层序遍历法. 当然,这里先找到root树的根 ...

  5. 03-树1. List Leaves (25)

    Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. I ...

  6. List Leaves

    Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. I ...

  7. 366. Find Leaves of Binary Tree输出层数相同的叶子节点

    [抄题]: Given a binary tree, collect a tree's nodes as if you were doing this: Collect and remove all ...

  8. CF&&CC百套计划4 Codeforces Round #276 (Div. 1) E. Sign on Fence

    http://codeforces.com/contest/484/problem/E 题意: 给出n个数,查询最大的在区间[l,r]内,长为w的子区间的最小值 第i棵线段树表示>=i的数 维护 ...

  9. 7-8 List Leaves(25 分)

    Given a tree, you are supposed to list all the leaves in the order of top down, and left to right. I ...

随机推荐

  1. MySQL架构及SQL语句

    MySQL基础: 单进程多线程: 用户连接:连接线程 官方组件架构: MySQL的数据文件类型: 数据文件.索引文件 重做日志.撤销日志.二进制日志.错误日志.查询日志.慢查询日志.中继日志 MySQ ...

  2. JumpServer里的sftp功能报错说明

    JumpServer里sftp默认的家目录是/tmp下 修改默认家目录: vim /usr/local/coco/coco/sftp.py class SFTPServer(paramiko.SFTP ...

  3. Android相关 博客收藏

    #1 Android 网络编程 参考博客 :http://blog.csdn.net/kieven2008/article/details/8210737 #2 Could not find com. ...

  4. asp.net core WebApi 快速入门

    参考:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.1 官网的例子 直接 ...

  5. jQuery字体缩放缩放插件zoomFontSize.js

    插件描述:jQuery字体缩放缩放插件zoomFontSize.js根据父类进行百分比缩放,兼容性如下: 使用方法 body 的class属性 添加 changbody_fontSize 而且整个页面 ...

  6. A - Exposition CodeForces - 6E

    题目链接:https://vjudge.net/contest/202699#problem/A 题意 给一个n个元素的序列,从中挑出最长的子序列,要求子序列中元素差的最大值不超过k.问有几个最长子序 ...

  7. [转]Prometheus 与 Grafana 实现服务器运行状态监控

    http://flintx.me/2017/12/12/Prometheus%20+%20Grafana%20%E5%AE%9E%E7%8E%B0%E6%9C%8D%E5%8A%A1%E5%99%A8 ...

  8. 在 Xshell 中 使用 hbase shell 进入后 无法删除 问题

    在 Xshell 中 使用 hbase shell 进入后 无法删除 问题: 在hbase shell下,误输入的指令不能使用backspace和delete删除,使用过的人都知道,这是有多坑,有多苦 ...

  9. (一)cygwin和vim——hello world!

    好吧,我现在初出茅庐,一无所有,只有一台win xp.做什么呢?要不要试试Unix命令行编程的感觉,想到就做.Just try! 1.首先安装cygwin,最好是选择离线安装包. 2.默认选择安装所有 ...

  10. 【转】Windows Server 2008 R2下安装 .net framework3.5

    原文地址:http://hi.baidu.com/tonny_dxf/item/6831bcdc3d7c06e7b2f7777c      [你必须用角色管理工具安装.net framework3.5 ...