【BZOJ 3083】遥远的国度

BZOJ 3083 遥远的国度

这题的与 HAOI 2015T2 的不同点在于其有换根操作,但按照普通的思路我们可以发现,换根之后树的形态会有改变,每个节点的子树会发生改变,所以我们来分类讨论。

修改链的操作不会发生改变,现在只考虑子树minn。为了方便,我们定义现在的换的“根节点”为root(但实际上树的根节点为1),子树根为x,黑圈标明查询范围;

情况一   x=root,很显然此时应当查询整棵树。


情况二 lca(root,x)!=x ,此时直接查询x的子树即可,与换根无关。

情况三,lca(root,x)=x,此时我们应当查询与x相邻的节点中与root最近的点v在整棵树中的补集

可以发现v一定在root到x的链上,且一定是x在这条链上的儿子,倍增法可以求得v

code:

#include
#include
#include
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
#define inf 2147483647
using namespace std;
struct hp{
	int fat,dep,size,wson,top,ls,rs;
	int lca[18];
}tree[100001];
struct hq{
	int u,v;
}a[200001];
struct hr{
	int minn,delta;
}seg[400001];
int point[100001],next[100001];
int val[400001],plc[100001];
int n,m,ans,e=1,totw=0,root;
void add(int x,int y)
{
	e++; a[e].u=x; a[e].v=y; next[e]=point[x]; point[x]=e;
	e++; a[e].u=y; a[e].v=x; next[e]=point[y]; point[y]=e;
}
void build_tree(int last,int x,int depth)
{
	int i;
	tree[x].lca[0]=tree[x].fat=last;
	tree[x].size=1;
	tree[x].wson=0;
	tree[x].dep=depth;
	for (i=1;i<=17;++i)
	  {
	    if (tree[x].dep >= 1<=r)
	  {
	    paint(i,a);
	    return;
	  }
	if (seg[i].delta!=0)
	  pushdown(i);
	if (x<=mid) insert_seg(lch,x,y,a);
	if (y>mid) insert_seg(rch,x,y,a);
	updata(i);
} 
void insert(int x,int y,int a)
{
	int f1=tree[x].top,f2=tree[y].top;
	while (f1!=f2)
	  {
	    if (tree[f1].deptree[y].dep) swap(x,y);
	insert_seg(1,1,n,plc[x],plc[y],a);
}
int bz(int x,int depth)
{
	int i,v=x;
	for (i=0;i<=17;++i)
	  {
	    if (depth&(1<=r)
	  {
	    ans=min(ans,seg[i].minn);
	    return;
	  }
	if (seg[i].delta!=0)
	  pushdown(i);
	if (x<=mid) query_seg(lch,x,y);
	if (y>mid) query_seg(rch,x,y);
} 
int LCA(int x,int y)
{
	int i,t;
	if (tree[x].dep=0;--i)
	  if (tree[x].lca[i]!=tree[y].lca[i])
	    {x=tree[x].lca[i]; y=tree[y].lca[i];}
	if (x==y) return x;
	else return tree[x].fat;
}
void work(int x)
{
	int lca,v,rootx=root,xx=x;
	lca=LCA(root,x);
	if (rootx==xx)//情况1
	  printf("%d\n",seg[1].minn);
	else
	  {
	    if (lca!=xx)//情况2
	      query_seg(1,1,n,tree[xx].ls,tree[xx].rs);
	    else//情况三
	      {
	        v=bz(rootx,tree[rootx].dep-tree[xx].dep-1);
	        if (tree[v].ls>1)
	          query_seg(1,1,n,1,tree[v].ls-1);
	        if (tree[v].rs

你可能感兴趣的:(数据结构,树上算法)