【BZOJ】【P2870】【最长道路tree】【题解】【点分……树?】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2870

看完就想到点分治了

可是用传统的点分治合并两条子树的链的时候很蛋疼……

于是我们换个方式

找到重心后把子树分成两堆,统计过根且起始结束位置在两个不同的堆里的答案

递归两堆子树

这种思想很早就有了 http://hi.baidu.com/345585690/item/fc3d0dd3167c28896cce3f09 http://blog.sina.com.cn/s/blog_76f6777d0101imnn.html

而且也不是很难写

如果把分治过程记录下来就可以做到动态修改询问,不过好像没人给这种数据结构起名字(或者我太弱了不知道)……

我就给它起名叫点分树了……

边分加虚点,括号序列什么的都太神了不会

好像树上点/链修改,整体/子树 路径查询的题不多……(QTREE有几个,wc,zjoi也有)

似乎可以有一大波新题诞生(又要被D了233)?

不过说起来这道题是静态的我在这扯什么蛋……

马上就去写1095

Code:

#include
using namespace std;
const int maxn=50010;
int getint(){
	int res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res;
}
vectorG[maxn];
int n,f[maxn],siz[maxn],w[maxn],d[maxn],root,dep[maxn];
int cant[maxn];
long long ans;
void makert(int u,int All,int fa,int &root){
	siz[u]=1;f[u]=0;
	for(int i=0,v;if[u])root=u;
}
int dsize,dsize2,tsize;
pair data[maxn],data2[maxn];
pair tmp[maxn];
void dfs(int u,int fa){
	data[++dsize]=make_pair(d[u],dep[u]);
	for(int i=0,v;i=(All+1)/2||used+1==can)break;
	}dsize=0;dep[u]=0;d[u]=w[u];dfs(u,u);dsize2=dsize;
	copy(data+1,data+1+dsize,data2+1);
	for(int i=0,v;i=1;i--)
	if(data[i].second>maxy)tmp[++tsize]=data[i],maxy=data[i].second;
	copy(tmp+1,tmp+1+tsize,data+1);dsize=tsize;maxy=-1;tsize=0;
	for(int i=dsize2;i>=1;i--)
	if(data2[i].second>maxy)tmp[++tsize]=data2[i],maxy=data2[i].second;
	copy(tmp+1,tmp+1+tsize,data2+1);dsize2=tsize;
	sort(data+1,data+1+dsize);
	sort(data2+1,data2+1+dsize2);
	for(int i=1;i<=dsize;i++){
		ans=max(ans,(long long)data[i].first*(data[i].second+1));
		pair *x=lower_bound(data2+1,data2+1+dsize2,make_pair(data[i].first,-1));
		if(x==data2+1+dsize2)continue;
		ans=max(ans,(long long)(data[i].second+x->second+1)*data[i].first);
	}
	for(int i=1;i<=dsize2;i++){
		ans=max(ans,(long long)data2[i].first*(data2[i].second+1));
		pair *x=lower_bound(data+1,data+1+dsize,make_pair(data2[i].first,-1));
		if(x==data+1+dsize)continue;
		ans=max(ans,(long long)(data2[i].second+x->second+1)*data2[i].first);
	}		
	if(sum+1>2)
	solve(u,sum+1);
	for(int i=0,v;i2)
	solve(u,All-sum);
	for(int i=0;i



你可能感兴趣的:(OI)