传送门

题意简述:

捉迷藏强化版(带有边权,可以为负数)


思路:好吧这次我们不用点分树,我们用听起来更屌的链分治

直接把树剖成若干条重链,这样保证从任意一个点跳到根节点是不会跳超过logloglog条重链的。

然后用上链分治的常规套路:分是否在链上面的信息讨论,并将整条链的值全部统计在链顶,这样修改的时候沿着链往上跳修改logloglog次即可。

那么针对这道题可以怎么瞎搞维护呢?

考虑对每个点构建一个大根堆hih_ihi​来维护它的子树去掉重儿子所在子树一位的点到它的距离的最值。

显然这个是可以从它的轻儿子们的答案转移过来的。

然后怎么维护整棵子树的最值呢?

对于每条重链我们开一棵线段树,把它们从上到下映射成一段连续的从左到右的区间,这样链顶对应最左端点,链底对应最右端点。

我们的线段树节点维护到区间最左端的最大值,到最右端的最大值,区间中相距最大的距离。

这个转移神似最大子段和,大家自己yyyyyy吧。

细节较多,详细的可以看代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ~w?ans:-ans;
}
typedef pair<int,int> pii;
const int N=1e5+5,inf=1<<28;
int n,m,siz[N],top[N],num[N],pred[N],bot[N],fa[N],hson[N],f[N],a[N],dis[N],tot=0;
bool col[N];
vector<pii>e[N];
struct deletable_heap{
	priority_queue<int>a,b;
	inline void push(const int&x){a.push(x);}
	inline void del(const int&x){b.push(x);}
	inline int top(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();return a.top();}
	inline void pop(){while(b.size()&&a.top()==b.top())a.pop(),b.pop();a.pop();}
	inline int size(){return a.size()-b.size();}
	inline int stop(){int tmp=top(),ret;return pop(),ret=top(),push(tmp),ret;}
	inline void f(int x,int&a,int&b,int&c){
		pii ret=pii(-inf,-inf);
		if(!col[x])ret.fi=ret.se=0;
		if(size())ret.fi=max(ret.fi,top());
		if(size()>1)ret.se=max(ret.se,stop());
		a=b=ret.fi,c=!col[x]?max(ret.fi,ret.fi+ret.se):ret.fi+ret.se;
	}
}h[N],Ans;
inline int max(const int&a,const int&b){return a>b?a:b;}
inline int max(const int&a,const int&b,const int&c){return max(max(a,b),c);}
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (T[p].l+T[p].r>>1)
	struct Node{int l,r,sum,ls,rs,ms;}T[N<<2];
	inline Node operator+(const Node&a,const Node&b){
		Node ret;
		ret.l=a.l,ret.r=b.r;
		int tmp=dis[pred[b.l]]-dis[pred[a.r]];
		ret.sum=a.sum+tmp+b.sum;
		ret.ls=max(a.ls,a.sum+tmp+b.ls);
		ret.rs=max(b.rs,b.sum+tmp+a.rs);
		ret.ms=max(a.ms,b.ms,a.rs+tmp+b.ls);
		return ret;
	}
	inline void Set(int p){
		int k=pred[T[p].l];
		T[p].sum=0,h[k].f(k,T[p].ls,T[p].rs,T[p].ms);
	}
	inline void pushup(int p){T[p]=T[lc]+T[rc];}
	inline void build(int p,int l,int r){
		T[p].l=l,T[p].r=r;
		if(l==r)return;
		build(lc,l,mid),build(rc,mid+1,r);
	}
	inline void update(int p,int k){
		if(T[p].l==T[p].r)return Set(p);
		update(k<=mid?lc:rc,k),pushup(p);
	}
	inline Node query(int p,int ql,int qr){
		if(ql<=T[p].l&&T[p].r<=qr)return T[p];
		if(qr<=mid)return query(lc,ql,qr);
		if(ql>mid)return query(rc,ql,qr);
		return query(lc,ql,qr)+query(rc,ql,qr);
	}
	#undef lc
	#undef rc
	#undef mid
}
void dfs1(int p){
	siz[p]=1;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i].fi)==fa[p])continue;
		fa[v]=p,dis[v]=dis[p]+e[p][i].se,dfs1(v),siz[p]+=siz[v];
		if(siz[v]>siz[hson[p]])hson[p]=v;
	}
}
void dfs2(int p,int tp){
	top[p]=tp,pred[num[p]=++tot]=p,bot[tp]=p;
	if(!hson[p])return;
	dfs2(hson[p],tp);
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i].fi)==fa[p]||v==hson[p])continue;
		dfs2(v,v);
	}
}
int dfs3(int p){
	for(ri x=p;x;x=hson[x]){
		for(ri i=0,v;i<e[x].size();++i){
			if((v=e[x][i].fi)==hson[x]||v==fa[x])continue;
			h[x].push(dfs3(v)+e[x][i].se);
		}
		SGT::update(1,num[x]);
	}
	SGT::Node tmp=SGT::query(1,num[p],num[bot[p]]);
	return Ans.push(tmp.ms),tmp.ls;
}
inline void update(int p){
	while(p){
		int ft=fa[top[p]],tp=top[p];
		SGT::Node tmp=SGT::query(1,num[top[p]],num[bot[top[p]]]);
		Ans.del(tmp.ms);
		if(ft)h[ft].del(tmp.ls+dis[tp]-dis[ft]);
		SGT::update(1,num[p]);
		tmp=SGT::query(1,num[top[p]],num[bot[top[p]]]);
		Ans.push(tmp.ms);
		if(ft)h[ft].push(tmp.ls+dis[tp]-dis[ft]);
		p=ft;
	}
}
char s[2];
int main(){
	n=read();
	for(ri i=1,u,v,w;i<n;++i){
		u=read(),v=read(),w=read();
		e[u].push_back(pii(v,w));
		e[v].push_back(pii(u,w));
	}
	dfs1(1),dfs2(1,1);
	SGT::build(1,1,n);
	dfs3(1);
	for(ri all=n,tt=read();tt;--tt){
		scanf("%s",s);
		if(s[0]=='A'){
			if(all>1)cout<<Ans.top()<<'\n';
			else if(all==1)puts("0");
			else puts("They have disappeared.");
		}
		else{
			int x=read();
			col[x]^=1;
			if(col[x])--all;
			else ++all;
			update(x);

		}
	}
	return 0;
}

2019.02.16 spoj Query on a tree IV(链分治)的更多相关文章

  1. 2019.02.17 spoj Query on a tree VII(链分治)

    传送门 跟QTREE6QTREE6QTREE6神似,改成了求连通块里的最大值. 于是我们对每条链开一个heapheapheap维护一下即可. MDMDMD终于1A1A1A链分治了. 代码: #incl ...

  2. 2019.02.17 spoj Query on a tree VI(链分治)

    传送门 题意简述:给你一棵nnn个黑白点的树,支持改一个点的颜色,询问跟某个点颜色相同的连通块大小. 思路: 还是链分治 233 记fi,0/1f_{i,0/1}fi,0/1​表示iii的所有颜色为0 ...

  3. 2019.02.17 spoj Query on a tree V(链分治)

    传送门 题意简述: 给你一棵nnn个黑白点的树,初始全是黑点. 现在支持给一个点换颜色或者求整颗树中离某个点最近的白点跟这个点的距离. 思路: 考虑链分治维护答案,每个链顶用一个堆来维护答案,然后对于 ...

  4. SPOJ Query on a tree 树链剖分 水题

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  5. 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. ...

  6. SPOJ QTREE4 - Query on a tree IV 树分治

    题意: 给出一棵边带权的树,初始树上所有节点都是白色. 有两种操作: C x,改变节点x的颜色,即白变黑,黑变白 A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0). 分析: ...

  7. SPOJ - QTREE4 Query on a tree IV 边分治

    题目传送门 题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有2个操作,1修改某个点的颜色, 2询问2个白点的之前的路径权值最大和是多少. 题解: 边分治思路. 1.重构图. 因为边分治 ...

  8. SPOJ QTREE Query on a tree 树链剖分+线段树

    题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...

  9. spoj 375 Query on a tree (树链剖分)

    Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges ...

随机推荐

  1. 网络之TCP握手总结

    目录: 31.Tcp握手的一些问题? 21.Tcp三次握手及SYN攻击: 四次握手? 为什么建立连接是三次握手,而关闭连接却是四次挥手? 13.TCP释放连接四次握手 12.TCP建立连接三次握手 1 ...

  2. [SQL]查询整个数据库中某个特定值所在的表和字段的方法

    查询整个数据库中某个特定值所在的表和字段的方法 当数据库做的太庞大的时候,难免会出现忘记哪个值会存入哪个表的情况,于是在网上找到的如下解决办法. 通过做一个存储过程,只需要传入一个想要查找的值,即可查 ...

  3. OpenStack Mitaka/Newton/Ocata/Pike 各版本功能贴整理

    逝者如斯,刚接触OpenStack的时候还只是第9版本IceHouse.前几天也看到了刘大咖更新了博客,翻译了Mirantis博客文章<OpenStack Pike 版本中的 53 个新功能盘点 ...

  4. 【Linux命令】Linux下的tar压缩解压缩命令详解(转)

    tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个 ...

  5. SpringBoot,SpringCloud入门到精通最简单教程

    https://blog.csdn.net/ztx114/article/details/78091689

  6. gentoo ebuild 私人portage

    最近考虑搞个私人 portage, 用于一些软件的安装和管理. mkdir -p /usr/local/portage/app-misc/hello-world cd $_ cp /usr/porta ...

  7. nginx 返回数据不完整

    当nginx 代理解析大量数据流时,会把数据先放在自己的缓冲区,然后一并发给客户端 一次请求的数据量很大, 则会有一部分数据会被忽略掉 前端解析数据会有问题 致使页面白屏 nginx 返回数据不完整的 ...

  8. Django模板语言相关内容 Djan

    Django模板语言相关内容   Django模板系统 官方文档 常用语法 只需要记两种特殊符号: {{  }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 {{ 变量名 }} ...

  9. 关于IE 浏览器的position居中定位的问题和 行块元素的设置问题

    这两天在写页面时,遇到一些IE浏览器显示不正常的问题,主要有两个: 1. 在td 中设置span 元素水平垂直居中,在谷歌浏览器中可以正常显示,但是在IE 中却无法显示出想要的结果,即不能实现垂直水平 ...

  10. Spring 4 官方文档学习 Web MVC 框架

    1.介绍Spring Web MVC 框架 Spring Web MVC 框架是围绕DispatcherServlet设计的,所谓DispatcherServlet就是将请求分发到handler,需要 ...