2851: 极限满月

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 170  Solved: 82
[Submit][Status][Discuss]

Description

Input

第一行一个正整数。
之后行描述集合。第一个数表示集合中元素的个数,之后给出集合中的元素。
之后一行一个正整数。
之后行每行描述一个询问。格式与之前相同。

Output

对于每个询问,在单独的一行内输出答案。

Sample Input

7
0
1 1
1 1
1 2
2 2 3
0
2 2 6
3
2 2 3
2 3 5
2 4 5

Sample Output

3
3
4

HINT

/*对于100% 的数据,1 <= n, m <= 50000,1 <= 10^9,-10^9 <= a, b, x, y <= 10^9。*/

[Discuss]里的正确数据范围:

n<=200000 m<=200000
A集合元素总个数<=300000
输入总数<=2500000

Source

Violet 0

想法:

如果把Bi当成红点,i当成蓝点,B0为一个虚红点,边V->U为U∈V。因为"a∈Ak=>a<k",所以每个Bi(i>0)红点只会连一个蓝点与一个红点。因此红点构成一棵树。

显然易见,Bi所连的红点为{Bj|j∈Ai}的lca。于是答案变成求集合{S}中所有红点所包含蓝点的并的大小。因为每个点蓝点只会被一个红点连边,所以可以把蓝点捆在该红点上,答案就变成统计{S}中所有红点的祖先并(除去B0虚红点)的大小。于是可以使用虚树或者树链的并解决。

复杂度O((∑|A|+∑|S|)logn).

细节:你会发现建红点树的过程是动态加点的在线求lca的过程。可以用倍增(仅支持加点)或LCT(支持加点删点换根....)解决。

#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm> typedef long long ll;
const int N();
struct Node
{
int nd,nx;
}bot[N];
int tot,first[N],depth[N],dfn[N],cnt;
void add(int a,int b){bot[++tot]=(Node){b,first[a]};first[a]=tot;}
int F[][N],logg;
int n,m,h[N],S;
std::vector<int>A[N];int sz,x;
template<class T>void read(T&x)
{
x=;bool f=;char c=getchar();
while((c<''||c>'')&&c!='-')c=getchar();if(c=='-')f=,c=getchar();
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
x=f?-x:x;
}
void swap(int &x,int &y){if(x==y)return;x^=y;y^=x;x^=y;}
int lca(int a,int b)
{
if(depth[a]<depth[b])swap(a,b);
// fprintf(stderr,"a:%d b:%d\b",a,b);
for(int k=depth[a]-depth[b],j=;k;k>>=,j++)
if(k&)a=F[j][a];
// fprintf(stderr,"a:%d b:%d\b",a,b);
if(a==b)return a;
for(int j=logg;F[][a]!=F[][b];j--)
if(F[j][a]!=F[j][b])a=F[j][a],b=F[j][b];
return F[][a];
}
void relax(int x)
{
for(int j=;j<=logg&&F[j-][x];j++)
F[j][x]=F[j-][ F[j-][x] ];
}
namespace GetTree
{
void init()
{
read(n);
for(int i=;i<=n;i++)
{
read(sz);
while(sz--) read(x),A[i].push_back(x);
std::sort(A[i].begin(),A[i].end());
}
}
void build()
{
logg=log2(n);
for(int i=,now;i<=n;i++)
{
now=n+;
if(A[i].size())
{
now=A[i][];
for(int v=,sz=A[i].size();v<sz;v++)
{
// fprintf(stderr,"now:%d\n",now);
now=lca(now,A[i][v]);
// fprintf(stderr,"A:%d\n",A[i][v]);
}
}
// fprintf(stderr,"now:%d\n",now);
F[][i]=now;depth[i]=depth[now]+;
add(now,i);
relax(i);
}
}
void DFS(int x)
{
dfn[x]=++cnt;
for(int v=first[x];v;v=bot[v].nx) DFS(bot[v].nd);
}
void run()
{
init();
build();
DFS(n+);
}
} bool cmp(int a,int b){return dfn[a]<dfn[b];}
void total()
{
std::sort(h+,h+S+,cmp);
int ans=;
for(int i=,t;i<=S;i++)
{
ans+=depth[h[i]];
// fprintf(stderr,"ans:%d\n",ans);
if(i>)
{
t=lca(h[i-],h[i]);
ans-=depth[t];
}
}
printf("%d\n",ans);
} int main()
{
// freopen("C.in","r",stdin);
GetTree::run();
read(m);
for(int i=;i<=m;i++)
{
read(S);
for(int j=;j<=S;j++) read(h[j]);
total();
}
return ;
}

BZOJ 2851: 极限满月 虚树 or 树链的并的更多相关文章

  1. [BZOJ 3489] A simple rmq problem 【可持久化树套树】

    题目链接:BZOJ - 3489 题目分析 “因为是OJ上的题,就简单点好了.”——出题人 真的..好..简单... 首先,我们求出每个数的前一个与它相同的数的位置,即 prev[i] ,如果前面没有 ...

  2. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  3. bzoj 1901: Zju2112 Dynamic Rankings(树套树)

    1901: Zju2112 Dynamic Rankings 经典的带改动求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过 ...

  4. BZOJ.3653.谈笑风生(长链剖分/线段树合并/树状数组)

    BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. ...

  5. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  6. bzoj 4031: 小Z的房间 矩阵树定理

    bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...

  7. [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表)

    [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表) 题面 Byteasar 想在墙上涂一段很长的字符,他为了做这件事从字符的前面一段中截取了一段 ...

  8. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

  9. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

随机推荐

  1. Gym - 100801H Hash Code Hacker (构造)

    题意:求 n 个哈希值相同的串. 析:直接构造,通过取模来查找相同的串. 代码如下: #pragma comment(linker, "/STACK:1024000000,102400000 ...

  2. JSP 标准标签库(JSTL)(菜鸟教程)

    菜鸟教程 JSTL 1.1 与 JSTL 1.2 之间的区别?如何下载 JSTL 1.2? JSTL 1.2 中不要求 standard.jar 包. 您可以在 Maven 中央仓库中找到它们. ht ...

  3. unity coroutine

    http://gad.qq.com/article/detail/695 使用Unity 3D引擎的同学,对于Coroutine(协程)的使用肯定也是非常熟悉的了.然而Coroutine背后的技术以及 ...

  4. Spfa算法模板

    输入点数n,边数m,起点终点边权 输出1号节点到所有点的最短路径长度 #include<iostream> #include<queue> #include<cstrin ...

  5. [Xcode 实际操作]六、媒体与动画-(12)检测UIView动画的结束事件:反转动画并缩小至不可见状态

    目录:[Swift]Xcode实际操作 本文将演示UIView视图反转动画的制作,并检测其动画结束事件. 即视图在进行反转动画的同时,将移动到目标位置,并缩小至不可见状态. 在项目导航区,打开视图控制 ...

  6. [Xcode 实际操作]六、媒体与动画-(8)使用CATransaction Reveal制作渐显动画

    目录:[Swift]Xcode实际操作 本文将演示如何制作渐显动画. 图片的不透明度逐渐发生了变化,从而产生作渐显动画的效果. 在项目导航区,打开视图控制器的代码文件[ViewController.s ...

  7. Sublime Text 3 最新注册码激活码 和 Sublime Text 2 注册码

    Sublime是一款很好用的很轻巧的编辑器,堪称一代神级编辑器.此篇文章用于简单学习记录下神器的激活码,不作其他用途.如有侵权,请联系删除,谢谢~~   1.官方下载地址: http://www.su ...

  8. Java:创建线程

    Java定义了两种创建线程的方法: 1.实现Runnable接口 要实现Runnable接口,只需简单地实现run()方法即可,声明如下:public void run() 在run()方法中,可以定 ...

  9. Etherscan API 中文文档-账号

    本文原文链接 点击这里获取Etherscan API 中文文档(完整版) 完整内容排版更好,推荐读者前往阅读. 账号(Account) 账号及地址相关的 API,接口的参数说明请参考Etherscan ...

  10. 目前最全的浏览器/CSS选择器兼容性总结(2009-8-10更新)

    2009年2月24日,Safari 4.0 beta版正式发布,Safari从它的3.2版本开始就已经支持所有的CSS选择器(包括最新的CSS3).不过为了方便大家的工作,下面提供了最新版本的CSS选 ...