【BZOJ1146】网络管理(整体二分)

【BZOJ1146】网络管理(整体二分)

题面

良心洛谷,有BZOJ权限题

题解

要看树套树的戳这里

毕竟是:智商不够数据结构来补

所以,
我们来当一回智商够的选手

听说主席树的题目大部分都可以整体二分

这题丢进去整体二分就行了
只需要查询树上贡献的前缀和
但是,对于这种带修改的
不能够直接修改
每一个修改操作必须拆成两个:
一个删掉原来的修改,一个加入现在的修改
否则就会重复计算贡献从而\(gg\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 81000
#define lson (now<<1)
#define rson (now<<1|1)
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int dfn[MAX],low[MAX],fa[MAX],size[MAX],hson[MAX],dep[MAX],top[MAX];
int tim,n,Q;
int LCA(int u,int v)
{
    while(top[u]!=top[v])
        dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
    return dep[u]<dep[v]?u:v;
}
void dfs1(int u,int ff)
{
    size[u]=1;fa[u]=ff;dep[u]=dep[ff]+1;
    for(int i=h[u];i;i=e[i].next)
    {
        if(e[i].v==ff)continue;
        dfs1(e[i].v,u);
        size[u]+=size[e[i].v];
        if(size[e[i].v]>size[hson[u]])hson[u]=e[i].v;
    }
}
void dfs2(int u,int tp)
{
    top[u]=tp;dfn[u]=++tim;
    if(hson[u])dfs2(hson[u],tp);
    for(int i=h[u];i;i=e[i].next)
    {
        if(e[i].v==fa[u]||e[i].v==hson[u])continue;
        dfs2(e[i].v,e[i].v);
    }
    low[u]=tim;
}
int sum,ans[MAX];
struct Op{int k,a,b,id,opt;}O[MAX<<1],p1[MAX<<1],p2[MAX<<1];
int c[MAX],TT[MAX];
int lowbit(int x){return x&(-x);}
void add(int x,int w){while(x<=n)c[x]+=w,x+=lowbit(x);}
int getsum(int x){int ret=0;while(x)ret+=c[x],x-=lowbit(x);return ret;}
int jump(int u,int v)
{
	int ret=0;
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		ret+=getsum(dfn[u])-getsum(dfn[top[u]]-1);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	ret+=getsum(dfn[u])-getsum(dfn[v]-1);
	return ret;
}
void Work(int L,int R,int l,int r)
{
	if(L>R)return;
	if(l==r)
	{
		for(int i=L;i<=R;++i)
			if(!O[i].opt&&ans[O[i].id]!=-1)ans[O[i].id]=l;
		return;
	}
	int mid=(l+r)>>1;
	int t1=0,t2=0;
	for(int i=L;i<=R;++i)
	{
		if(O[i].k==0)
		{
			if(O[i].b<=mid)p1[++t1]=O[i];
			else p2[++t2]=O[i],add(dfn[O[i].a],O[i].id);
		}
		else
		{
			int ss=jump(O[i].a,O[i].b);
			if(ss>=O[i].k)p2[++t2]=O[i];
			else O[i].k-=ss,p1[++t1]=O[i];
		}
	}
	for(int i=L;i<=R;++i)if(O[i].opt&&O[i].b>mid)add(dfn[O[i].a],-O[i].id);
	for(int i=1;i<=t1;++i)O[L+i-1]=p1[i];
	for(int i=1;i<=t2;++i)O[L+t1+i-1]=p2[i];
	Work(L,L+t1-1,l,mid);Work(L+t1,R,mid+1,r);
}
int main()
{
    n=read();Q=read();
	int Cnt=0;
	for(int i=1;i<=n;++i)
	{
		TT[i]=read();
		O[++Cnt]=(Op){0,i,TT[i],1,1};
	}
	for(int i=1;i<n;++i)
	{
		int u=read(),v=read();
		Add(u,v);Add(v,u);
	}
	dfs1(1,0);dfs2(1,1);
	for(int i=1;i<=Q;++i)
	{
		int k=read(),a=read(),b=read();
		if(k)
		{
			O[++Cnt]=(Op){k,a,b,++sum,0};
			int len=dep[O[Cnt].a]+dep[O[Cnt].b]-2*dep[LCA(O[Cnt].a,O[Cnt].b)]+1;
			if(O[Cnt].k>len)ans[O[Cnt].id]=-1;
		}
		else
		{
			O[++Cnt]=(Op){0,a,TT[a],-1,1};
			O[++Cnt]=(Op){0,a,TT[a]=b,1,1};
		}
	}
	Work(1,Cnt,1,1e8);
	for(int i=1;i<=sum;++i)
		ans[i]!=-1?printf("%d\n",ans[i]):puts("invalid request!");
	return 0;	
}

posted @ 2018-02-05 14:40  小蒟蒻yyb  阅读(285)  评论(2编辑  收藏  举报