其他分享
首页 > 其他分享> > 【2021 HDU多校集训第四场】1011. Travel on Tree

【2021 HDU多校集训第四场】1011. Travel on Tree

作者:互联网

Description

给你一颗n个点的树,边有边权。有m次询问,每次询问给出[l,r],要求编号为[l,r]之间的点组成的虚树边权和*2。

n , m ≤ 1 0 5 n,m\leq 10^5 n,m≤105
多组询问,最多10组极限数据,时限30s

Solution

用不带删除的莫队来做,

枚举 n \sqrt{n} n ​次起点,设为S,可以预处理出 S到S+1,S到S+2…,S到n 这n-S+1棵虚树的边权大小。
具体的,我们只需要维护每次往虚树中加一个点后,虚树权值的变化量,也就是找dfn第一个比当前点大和第一个比当前点小的点,
正着加点不好维护,考虑反过来做,就变成删点,这样就可以用并查集维护第一个比当前点大和第一个比当前点小的点,

对于每个询问,找暴力将小于S的那一部分点加进虚树中,

使用RMQ-LCA可以实现 O ( 1 ) O(1) O(1)的查询LCA,
复杂度: O ( n n ) O(n\sqrt{n}) O(nn ​)

卡常卡了半天QwQ

Code

#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N=100500,INF=1e9+7;
char bf[1000000], *kdp1 = bf, *kdp2 = bf;
#define nc() (kdp1==kdp2&&(kdp2=(kdp1=bf)+fread(bf,1,1000000,stdin),kdp2==kdp1)?-1:*kdp1++)
inline int read(int &x) {
    x = 0;
    char ch = nc();
    for (; ch < '0' || ch > '9'; ch = nc());
    for (; ch <= '9' && ch >= '0'; x = x * 10 + ch - 48, ch = nc());
    return x;
}
char pf[20000000],*kxo1=pf,*kxo2=pf+20000000;
#define ot(x) (kxo1==kxo2?fwrite(pf,1,20000000,stdout),*(kxo1=pf)++=x:*kxo1++=x)
inline void print(LL x){static char s[20],*b;b=s;if(!x)*b++=48;for(;x;*b++=x%10+48,x/=10);for(;b--!=s;ot(*b));}

int n,m,ans;
int B[N*2][3],A[N],B0;
vector<pii>GU[N];
LL Ans[N];
void link(int q,int w,int e)
{
	B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w;B[B0][2]=e;
	B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q;B[B0][2]=e;
}

int dfn[N],dzx[N],dep[N];//
LL dis[N];

pii rmq[N*2][20];
int er[22],lg2[N*2];
int rzx[N],rmq0;
void dfsf(int q,int fa,int fav)
{
	dzx[dfn[q]=++dfn[0]]=q;
	dep[q]=dep[fa]+1;
	dis[q]=dis[fa]+fav;
	
	rmq[rzx[q]=++rmq0][0]={dep[q],q};
	efo(i,q)if(B[i][1]!=fa)
	{
		dfsf(B[i][1],q,B[i][2]);
		rmq[++rmq0][0]={dep[q],q};
	}
}

struct ASKv
{
	int l,r,L,i;
}ask[N];
LL f[N];

int ff[N][2];
LL ffv[N][3];

int G[2][N];
int gf(int I,int q){return G[I][q]==q?q:G[I][q]=gf(I,G[I][q]);}
int LCA(int q,int w)
{
	int l=rzx[q],r=rzx[w];
	if(l>r)swap(l,r);
	int t=lg2[r-l+1];
	return min(rmq[l][t],rmq[r-er[t]+1][t]).second;
}
int p[N],p1[500],p2[500];
void baoli(int aS,int la)
{
	int l=ask[aS].l,r=ask[aS].r;

	p[0]=0;
	if(l>=la)
	{
		fo(j,1,p2[0])if(p2[j]>=l&&p2[j]<=r)p[++p[0]]=p2[j];
	}
	else {
		fo(j,1,p1[0])if(p1[j]>=l&&p1[j]<=r)p[++p[0]]=p1[j];
	}
	LL ans=0;
	p[p[0]+1]=p[1];
	fo(j,2,p[0]+1)
	{
		int w=LCA(p[j],p[j-1]);
		ans+=dis[p[j-1]]+dis[p[j]]-2*dis[w];
	}
	Ans[ask[aS].i]=ans;
}
void resetG(int S)
{
	fo(i,1,S-1)
	{
		int q=dfn[i];
		G[0][q]=q-1;
		G[1][q]=q+1;
	}
	fo(i,S,n)
	{
		int q=dfn[i];
		G[0][q]=G[1][q]=q;
	}
	G[0][n+1]=G[1][n+1]=n+1;
}
void init()
{
	int q,w,e;
	read(n),read(m);
	fo(i,2,n)read(q),read(w),read(e),link(q,w,e);
	int K=sqrt(n)+1;
	K=min(n,K);
	fo(i,1,m)
	{
		read(ask[i].l),read(ask[i].r);
		ask[i].i=i;
		ask[i].L=(ask[i].l-1)/K;
	}
	sort(ask+1,ask+1+m,[](ASKv q,ASKv w){return q.L<w.L||(q.L==w.L&&q.r<w.r);});

	dfsf(1,0,0);
	fo(j,1,18)
	{
		fo(i,1,rmq0-er[j-1])rmq[i][j]=min(rmq[i][j-1],rmq[i+er[j-1]][j-1]);
	}

	int STR=clock();
	int aS=1;
	for(int S=K,la=0,kn=1;1;++kn,la=S,S=min(n,S+K))
	{
		// printf("%d %d\n",S,clock()-STR);
		STR=clock();

		p1[0]=0;
		fo(i,la+1,S-1)p1[++p1[0]]=i;
		sort(p1+1,p1+1+p1[0],[](int q,int w){return dfn[q]<dfn[w];});
		p2[0]=0;
		fo(i,la+1+(K>>1),S-1)p2[++p2[0]]=i;
		sort(p2+1,p2+1+p2[0],[](int q,int w){return dfn[q]<dfn[w];});

		int mx=0;
		for(;aS<=m&& ask[aS].L==kn-1;++aS)
		{
			if(ask[aS].r<S)
			{
				baoli(aS,la+1+(K>>1));
			}else {
				GU[ask[aS].r].push_back({ask[aS].l,ask[aS].i});
				mx=max(mx,ask[aS].r);
			}
		}

		resetG(S);

		// printf("  %d\n",clock()-STR);
		
		f[S]=0;

		fod(i,n,mx+1)q=dfn[i],G[0][q]=q-1,G[1][q]=q+1;
		fod(i,mx,S)
		{
			for(auto nw:GU[i])
			{
				int l=nw.first;
				p[0]=0;
				if(l>=la+1+(K>>1))
				{
					fo(j,1,p2[0])if(p2[j]>=l)p[++p[0]]=p2[j];
				}
				else {
					fo(j,1,p1[0])if(p1[j]>=l)p[++p[0]]=p1[j];
				}
				LL ans=0;
				fo(j,1,p[0])
				{
					int l=dzx[gf(0,dfn[p[j]])];
					if(j>1&& (!l||dfn[l]<dfn[p[j-1]]))l=p[j-1];
					if(!l)l=dzx[gf(0,n)];

					int r=dzx[gf(1,dfn[p[j]])];
					if(!r)
					{
						r=dzx[gf(1,1)];
						if(j>1&& dfn[r]>dfn[p[1]])r=p[1];
					}

					ans-=dis[r]+dis[l]-2*dis[LCA(r,l)];
					ans+=dis[p[j]]+dis[l]-2*dis[LCA(p[j],l)];
					ans+=dis[p[j]]+dis[r]-2*dis[LCA(p[j],r)];
				}
				Ans[nw.second]=ans;
			}

			q=dfn[i];
			G[0][q]=q-1;
			G[1][q]=q+1;
			if(i==S)continue;

			int l,r;
			l=dzx[gf(0,q)];
			if(!l)l=dzx[gf(0,n)];
			
			r=dzx[gf(1,q)];
			if(!r)r=dzx[gf(1,1)];

			if(ff[i][0]!=l||ff[i][1]!=r)ffv[i][2]=-2*dis[LCA(l,r)];
			if(ff[i][0]!=l)ff[i][0]=l,ffv[i][0]=-2*dis[LCA(l,i)];
			if(ff[i][1]!=r)ff[i][1]=r,ffv[i][1]=-2*dis[LCA(r,i)];
			f[i]=dis[i]*2+ffv[i][0]+ffv[i][1]-ffv[i][2];

		}

		LL sum=0;
		GU[S].clear();
		fo(i,S+1,mx)
		{
			sum+=f[i];
			for(auto nw:GU[i])
			{
				Ans[nw.second]+=sum;
			}
			GU[i].clear();
		}
		if(S==n)break;
	}

	fo(i,1,m)
	{
		print(Ans[i]);
		ot('\n');
		// printf("%lld\n",Ans[i]);
	}
	
	B0=0;rmq0=0;
	fo(i,1,n)A[i]=dzx[i]=0;
	fo(i,1,n)
	{
		ff[i][0]=ff[i][1]=0;
		fo(j,0,2)ffv[i][j]=0;
	}
	dfn[0]=0;
}
int main()
{
	int STR=clock();
	int q,w,_;
	er[0]=1;fo(j,1,18)er[j]=er[j-1]<<1;
	fo(i,1,200000)lg2[i]=log2(i);
	read(_);
	while(_--)
	{
		init();
	}
	cerr<<clock()-STR<<endl;
	fwrite(pf,1,kxo1-pf,stdout);
	return 0;
}

标签:HDU,第四场,int,Travel,++,dfn,ask,dis,fo
来源: https://blog.csdn.net/HOWARLI/article/details/119245434