qtree4
https://zybuluo.com/ysner/note/1236834
题面
给出一棵边带权的节点数量为\(n\)的树,初始树上所有节点都是白色。有两种操作:
- 改变节点\(x\)的颜色,即白变黑,黑变白
- 询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为\(0\))。
\(n\leq10^5,q\leq2*10^5\)
解析
打这道题的过程中,\(get\)了许多新姿势。
点分治经典问题。每次分治时找到每棵子树深度最大的一个白点,用最大的两个统计一下即可。
找最大和次大自然需要堆,且每个点都需要开两个。
第一个堆插入这个重心管辖的一坨树所有白点到分治树上这个点父亲的距离。
第二个堆插入所有点分治树上孩子的堆顶,这样我们就可以对于每个分治重心,找到分属两棵子树的深度最大的两个白点,即这个点堆的最大和次大值。
修改就只要再点分树上从自己的重心往根走,然后维护一下那些堆。
注意这些堆要可删除(即可以指定删除其中一个元素)。
原理是每个堆里设一个删除堆和插入堆,插入元素就插入插入堆,删除元素就插入删除堆。如要取堆顶,就把两堆同时弹到堆顶不相等即可,取插入堆堆顶即可。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define re register
#define il inline
#define inf 1000000000
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=5e5+100;
struct Edge{int to,nxt,w;}e[N<<1];
struct dui
{
priority_queue<int>s,t;int sz;
il void pop(re int x){t.push(x);--sz;}
il void push(re int x){s.push(x);++sz;}
il void pre(){while(t.size()&&s.top()==t.top()) s.pop(),t.pop();}
il int top(){pre();return sz?s.top():-inf;}
il int len()
{
if(sz<2) return 0;
re int x=top();pop(x);
re int y=top();push(x);
return max(x+y,0);
}
il void del(re int x,re int k){k?pop(x):push(x);}
}a[N],b[N],ans;
int n,h[N],cnt,Q,d[N],dis[N],f[N],sz[N],mx,mn,Sz[N],top[N],son[N],root,Size,F[N],w[N],tot,s[N],tim;
bool vis[N];
il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il void dfs1(re int u,re int fa)
{
d[u]=d[fa]+1;f[u]=fa;sz[u]=1;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==fa) continue;
dis[v]=dis[u]+e[i].w;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
il void dfs2(re int u,re int up)
{
top[u]=up;
if(son[u]) dfs2(son[u],up);
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==f[u]||v==son[u]) continue;
dfs2(v,v);
}
}
il int lca(re int u,re int v)
{
while(top[u]^top[v])
{
if(d[top[u]]<d[top[v]]) swap(u,v);
u=f[top[u]];
}
return d[u]<d[v]?u:v;
}
il int Dis(re int u,re int v){return dis[u]+dis[v]-2*dis[lca(u,v)];}
il void Getrt(re int u,re int fa)
{
re int mx=0;Sz[u]=1;s[++tim]=u;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(v==fa||vis[v]) continue;
Getrt(v,u);
Sz[u]+=Sz[v];
mx=max(mx,Sz[v]);
}
mx=max(mx,Size-Sz[u]);
if(mx<mn) mn=mx,root=u;
}
il int dfs(re int u,re int fa)
{
vis[u]=1;F[u]=fa;b[u].push(0);
if(F[u]) fp(i,1,tim) a[u].push(Dis(s[i],F[u]));
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to;
if(vis[v]) continue;
Size=Sz[v];mn=n;tim=0;
Getrt(v,u);
re int p=dfs(root,u);
b[u].push(a[p].top());
}
ans.push(b[u].len());
return u;
}
il void Modify(re int u,re int w)
{
re int l1=b[u].len(),l2,s1,s2;
b[u].del(0,w);l2=b[u].len();
if(l1^l2) ans.pop(l1),ans.push(l2);
for(re int i=u;F[i];i=F[i])
{
s1=a[i].top();
a[i].del(Dis(u,F[i]),w);
s2=a[i].top();
if(s1==s2) continue;
l1=b[F[i]].len();
if(s1!=-inf) b[F[i]].pop(s1);if(s2!=-inf) b[F[i]].push(s2);
l2=b[F[i]].len();
if(l1^l2) ans.pop(l1),ans.push(l2);
}
}
int main()
{
memset(h,-1,sizeof(h));
tot=n=gi();
fp(i,1,n-1)
{
re int u=gi(),v=gi(),w=gi();
add(u,v,w);add(v,u,w);
}
dfs1(1,0);dfs2(1,1);
Size=mn=n;Getrt(1,0);
dfs(root,0);
fp(i,1,n) w[i]=1;
Q=gi();
while(Q--)
{
re char op='0';while(op!='A'&&op!='C') op=getchar();
if(op=='A')
{
tot?printf("%d\n",tot==1?0:ans.top()):puts("They have disappeared.");
}
if(op=='C')
{
re int u=gi();tot+=(w[u]?-1:1);
Modify(u,w[u]);w[u]^=1;
}
}
return 0;
}
qtree4的更多相关文章
- 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)
题目链接 洛谷 SPOJ BZOJ1095(简化版) 将每次Solve的重心root连起来,会形成一个深度为logn的树,就叫它点分树吧.. 我们对每个root维护两个东西: 它管辖的子树中所有白点到 ...
- luogu P4115 Qtree4
题目链接 luogu P4115 Qtree4 题解 动态点分治,和上一题一样.同样三个堆.就是带权,用边权替换深度就好 为什么要单独写这个题解呢,因为我卡常卡了一天....据说树剖比rmq快? 在第 ...
- SPOJ2666 QTREE4
我是萌萌的传送门 我是另一个萌萌的传送门 一道树分治……简直恶心死了……我在调代码的时候只想说:我*************************************************…… ...
- 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV
意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...
- SPOJ QTREE4 lct
题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #i ...
- 洛谷 4115 Qtree4——链分治
题目:https://www.luogu.org/problemnew/show/P4115 论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb ...
- Qtree4——动态点分治
题目描述 给出一棵边带权的节点数量为n的树,初始树上所有节点都是白色.有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为 ...
- luoguP4115 QTREE4 链分治
具体看$qzc$论文吧......陈年老物了...... 主要注意每个链头一棵线段树而不是一棵全局线段树 修改操作写完就是正确的,反而是初始化调了好一会...... 跑的还是很快的,有些地方没优化常数 ...
- SP2666 QTREE4 - Query on a tree IV(LCT)
题意翻译 你被给定一棵n个点的带边权的树(边权可以为负),点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的权值之和. 一开始所有的点都是白色的. 要求作以下 ...
- SPOJ QTREE4 SPOJ Query on a tree IV
You are given a tree (an acyclic undirected connected graph) with N nodes, and nodes numbered 1,2,3. ...
随机推荐
- MxCAD5.2 20180726更新
下载地址: http://www.mxdraw.com/ndetail_105.html 1. 增加属性匹配功能 2. 增加List命令 3. 增加CAD图纸审图批注功能 4. 环形阵列功能
- 虚拟机下Linux网络配置
之前配置好了linux系统,在网络这块我用的是桥接模式. 现在分享一下使用虚拟机桥接模式配置Linux网络的过程. 一.首先配置外网的本地Ip地址. 二.配置Linux 网络链接 1.打开linux网 ...
- Xshell(smarTTY)连接Linux虚拟机失败(未开放22端口)解决办法
1.关闭防火墙: 命令:sudo ufw disable 2.安装openssh-server以及openssh-client: 命令:sudo apt-get install openssh-ser ...
- Jmeter BeanShell PreProcessor使用笔记
打印log log.info("content:" + content); 将字符串转化为JsonString import com.alibaba.fastjson.JSON; ...
- 00 大王警语--be_a_new_gentleman
大王博客:https://www.cnblogs.com/alex3714/ # 表面层次# 1,着装特体(服饰的牌子中高端)# 2,每天洗澡# 3,适当用香水# 4,女士优先# 5,不随地吐痰.不乱 ...
- E - Cricket Field
Description Once upon a time there was a greedy King who ordered his chief Architect to build a fi ...
- IIS301重定向:将不带www的域名跳转到带www上
首先你的域名有这两条解析记录 进入服务器IIS,添加2个站点,如下图 第一个正常绑定你的域名:www.baidu.com 第二个绑定不带www的域名:baidu.com 然后点开ncgd-no-www ...
- 常量Constant
常量通常指的是一个固定的值,例如:1.2.3.’a’.’b’.true.false.”helloWorld”等. 在Java语言中,主要是利用关键字final来定义一个常量. 常量一旦被初始化后不能再 ...
- 【Codeforces 924C】Riverside Curio
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 设第i天总共的线数为t[i] 水平线上线数为m[i]是固定的 水平线下的线数设为d[i] 则d[i]+m[i]+1=t[i] 也就是说问题可以 ...
- MongoDB怎么快速的删除数据库数据?
我的mongodb里有10+数据库.现在需要重置这个环境,得到干净的没有数据的MongoDB.怎么快速安全的删除这些数据库数据呢? 记得首先备份你的数据库mongodump -o bakfolder ...