【CF768G】The Winds of Winter 可持久化线段树 DFS序
题目大意
给定一棵\(n\)个点的树,对于树上每个结点,将它删去,然后可以将得到的森林中任意一个点与其父亲断开并连接到另一颗树上,对每一个点求出森林中所有树\(size\)最大值的最小值。
\(n\leq 100000\)
题解
首先用DFS序+可持久化线段树求出删掉这个点后剩下的联通块的大小的最大值\(max\)、次大值\(sec\)、最小值\(min\)。这里要维护两棵可持久化线段树,一棵是DFS序前缀的,一棵是从根到每个点的。
那么肯定是在最大的连通块上切下一块接到最小的连通块上。
假设切下的大小为\(x\),那么答案是\(\max(max-x,min+x,sec)\)。这个的图像是带一个向下的尖角的,这个尖角的位置为\(\frac{max+min}{2}\)。所以我们要切下来的\(x\)就是\(\frac{max-min}{2}\)。我们只需要在对应的可持久化线段树上找这个值的前驱和后继并统计答案。
切下来的部分有三种可能:
1.在\(x\)的子树内,可以直接统计答案
2.在\(x\)的子树外且不包含\(x\)到根的点,可以直接统计答案
3.在\(x\)的子树外切包含根到\(x\)的点,查询到的子树大小要减掉\(size_x\)
时间复杂度:\(O(n\log n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<list>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace sgt
{
int rt1[100010];
int rt2[100010];
struct node
{
int lc,rc;
int s;
node()
{
lc=rc=s=0;
}
};
node a[10000010];
int cnt=0;
int insert(int p1,int x,int l,int r)
{
int p=++cnt;
a[p]=a[p1];
a[p].s++;
if(l==r)
return p;
int mid=(l+r)>>1;
if(x<=mid)
a[p].lc=insert(a[p].lc,x,l,mid);
else
a[p].rc=insert(a[p].rc,x,mid+1,r);
return p;
}
int suf(int p1,int p2,int p3,int p4,int x,int l,int r)//p1+p3-p2-p4
{
int s=a[p1].s+a[p3].s-a[p4].s-a[p2].s;
if(!s)
return 0x3fffffff;
if(l==r)
return l;
int mid=(l+r)>>1;
int ls=a[a[p1].lc].s+a[a[p3].lc].s-a[a[p4].lc].s-a[a[p2].lc].s;
if(x<=mid&&ls)
{
int lans=suf(a[p1].lc,a[p2].lc,a[p3].lc,a[p4].lc,x,l,mid);
if(lans!=0x3fffffff)
return lans;
}
return suf(a[p1].rc,a[p2].rc,a[p3].rc,a[p4].rc,x,mid+1,r);
}
int pre(int p1,int p2,int p3,int p4,int x,int l,int r)
{
int s=a[p1].s+a[p3].s-a[p4].s-a[p2].s;
if(!s)
return 0;
if(l==r)
return l;
int mid=(l+r)>>1;
int rs=a[a[p1].rc].s+a[a[p3].rc].s-a[a[p4].rc].s-a[a[p2].rc].s;
if(x>mid&&rs)
{
int rans=pre(a[p1].rc,a[p2].rc,a[p3].rc,a[p4].rc,x,mid+1,r);
if(rans)
return rans;
}
return pre(a[p1].lc,a[p2].lc,a[p3].lc,a[p4].lc,x,l,mid);
}
int getmax(int p1,int p2,int p3,int p4,int l,int r)
{
int s=a[p1].s+a[p3].s-a[p4].s-a[p2].s;
if(!s)
return 0;
if(l==r)
return l;
int mid=(l+r)>>1;
int rs=a[a[p1].rc].s+a[a[p3].rc].s-a[a[p4].rc].s-a[a[p2].rc].s;
if(rs)
return getmax(a[p1].rc,a[p2].rc,a[p3].rc,a[p4].rc,mid+1,r);
return getmax(a[p1].lc,a[p2].lc,a[p3].lc,a[p4].lc,l,mid);
}
int getmin(int p1,int p2,int p3,int p4,int l,int r)
{
int s=a[p1].s+a[p3].s-a[p4].s-a[p2].s;
if(!s)
return 0x3fffffff;
if(l==r)
return l;
int mid=(l+r)>>1;
int ls=a[a[p1].lc].s+a[a[p3].lc].s-a[a[p4].lc].s-a[a[p2].lc].s;
if(ls)
return getmin(a[p1].lc,a[p2].lc,a[p3].lc,a[p4].lc,l,mid);
return getmin(a[p1].rc,a[p2].rc,a[p3].rc,a[p4].rc,mid+1,r);
}
}
using sgt::rt1;
using sgt::rt2;
using sgt::insert;
using sgt::suf;
using sgt::pre;
using sgt::getmax;
using sgt::getmin;
list<int> l[100010];
int f[100010];
int st[100010];
int ed[100010];
int s[100010];
int w[100010];
int ti;
int n;
void dfs1(int x)
{
st[x]=++ti;
w[ti]=x;
s[x]=1;
for(auto v:l[x])
{
dfs1(v);
s[x]+=s[v];
}
ed[x]=ti;
}
int update(int &a,int &b,int &c)
{
if(c>=a)
{
b=a;
a=c;
return 1;
}
else
{
b=max(b,c);
return 2;
}
return 0;
}
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d",&n);
int rt,x,y;
int i;
for(i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
if(x)
{
l[x].push_back(y);
f[y]=x;
}
else
rt=y;
}
dfs1(rt);
for(i=1;i<=n;i++)
{
x=w[i];
rt2[x]=insert(rt2[f[x]],s[x],1,n);
rt1[i]=insert(rt1[i-1],s[x],1,n);
}
for(i=1;i<=n;i++)
{
int mx=0,sec=0,mi=0x7fffffff;
int s1,s2,s3,s4,ans;
int mv;
for(auto v:l[i])
{
s1=s[v];
if(update(mx,sec,s1)==1)
{
s4=1;
mv=v;
}
mi=min(mi,s1);
}
s1=n-s[i];
if(s1)
{
if(update(mx,sec,s1)==1)
s4=2;
mi=min(mi,s1);
}
ans=0x7fffffff;
int mid=(mi+mx+1)>>1;
int s5=mx-mid;
if(i==1)
int xxx=1;
ans=min(ans,mx);
if(s4==1)
{
s1=pre(rt1[ed[mv]],rt1[st[mv]-1],0,0,s5,1,n);
s2=suf(rt1[ed[mv]],rt1[st[mv]-1],0,0,s5,1,n);
ans=min(ans,max(sec,max(mi+s1,mx-s1)));
ans=min(ans,max(sec,max(mi+s2,mx-s2)));
}
else if(s4==2)
{
s1=pre(rt2[f[i]],0,0,0,s5+s[i],1,n);
s2=suf(rt2[f[i]],0,0,0,s5+s[i],1,n);
if(s1)
s1-=s[i];
if(s2!=0x3fffffff)
s2-=s[i];
ans=min(ans,max(sec,max(mi+s1,mx-s1)));
ans=min(ans,max(sec,max(mi+s2,mx-s2)));
s1=pre(rt1[st[i]-1],rt1[ed[i]],rt1[n],rt2[f[i]],s5,1,n);
s2=suf(rt1[st[i]-1],rt1[ed[i]],rt1[n],rt2[f[i]],s5,1,n);
ans=min(ans,max(sec,max(mi+s1,mx-s1)));
ans=min(ans,max(sec,max(mi+s2,mx-s2)));
}
printf("%d\n",ans);
}
return 0;
}
【CF768G】The Winds of Winter 可持久化线段树 DFS序的更多相关文章
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- BZOJ3653谈笑风生——可持久化线段树+dfs序
题目描述 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道 高明到哪里去了”. ? 设a 和 b 为 T 中的两个不同节点.如果 a ...
- BZOJ_3252_攻略_线段树+dfs序
BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...
- 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
题目大意 Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- S - Query on a tree HDU - 3804 线段树+dfs序
S - Query on a tree HDU - 3804 离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...
- HDU 5692 线段树+dfs序
Snacks Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序
3779: 重组病毒 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 224 Solved: 95[Submit][Status][Discuss] ...
- 【BZOJ-3306】树 线段树 + DFS序
3306: 树 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 792 Solved: 262[Submit][Status][Discuss] De ...
随机推荐
- Python-SMTP发送邮件(HTML、图片、附件)
前言: SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式. 一.Python发送HTML ...
- python线程中的全局变量与局部变量
在python多线程开发中,全局变量是多个线程共享的数据,局部变量是各自线程的,非共享的. 如下几种写法都是可以的: 第一种:将列表当成参数传递给线程 from threading import Th ...
- BZOJ1969 航线规划
给定一个无向图,每次删除一条边,求每次有多少关键边.一条边是关键边,当且仅当从1到n的所有路径都包含这条边.所有时刻图都联通. 考虑倒着做.相当于给一棵树,每次加一条边,这样树上这条边的两个端点间的路 ...
- nginx的The page you are looking for is temporarily unavailable错误解决办法
访问网站时出现如下错误,如下图: 检查php fastcgi进程数,如下图: 输出0则表示fastcgi进程数够大,修改scgi_params文件,如下图: 然后重启php-fpm和nginx,重新访 ...
- echarts各个配置项详细说明总结
https://blog.csdn.net/sinat_34492035/article/details/70258557 https://blog.csdn.net/qq_34908167/arti ...
- 福州大学软件工程1816 | W班 第10次作业[个人作业——软件产品案例分析]
作业链接 个人作业--软件产品案例分析 评分细则 本次个人项目分数由两部分组成(课堂得分(老师/助教占比60%,学生占比40%)满分40分+博客分满分60分) 课堂得分和博客得分表 评分统计图 千帆竞 ...
- 软件工程(FZU2015) 赛季得分榜,第五回合
SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分=团队得分+个人贡献分 个人贡献分: 个人 ...
- 持续集成之Jenkins自动部署war包到远程服务器
一.无war包链接的情况 无war包链接时,需先下载war包到本地,然后执行: ---------------------------------------------以下部分为转载-------- ...
- Java面试题详解四:==和equals的去别
一,功能 1.对于== 作用于基本数据类型的变量,比较的存储的值是否相等, 作用于引用类型的变量,比较的是其所指向的对象的地址是否相同(即是否是同一个对象) 2.对于equals Object的equ ...
- 高阶组件 HOC
一. A higher-order component (HOC) is an advanced technique in React for reusing component logic. a h ...