ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-07-30 13:34:10  阅读:195  来源: 互联网

标签:HDU 第四场 int Travel ++ dfn ask dis fo


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有