世末农庄

  • 赛后独立做出了这道题,开心~
  • 在随机数据下,朴素维护已经是一个比较高效的过程了
  • 考虑特殊情形1:链,引入树链剖分算法(链上的每一条边都是重边)
  • 考虑特殊情形2:菊花图,倍增法查找后继节点
  • 节点的w为0不完全等价于该点已失去价值——也可能是遭遇了蝗灾
点击查看代码
#include <bits/stdc++.h>
using namespace std;
long long p[200005],w[200005];
int opt[200005],u[200005],v[200005],k[200005],s[200005],l[200005];
vector<int>a[200005],sa[200005];
int dfn[200005],sz[200005],h[200005],fa[200005],la[200005],d[200005],tot,pre[300005];
bool e[200005];
int read1()
{
	char cc=getchar();
	while(!(cc>=48&&cc<=57))
	{
		if(cc=='-')
		{
			break;
		}
		cc=getchar();
	}
	bool f=false;
	int s=0;
	if(cc=='-')
	{
		f=true;
	}
	else
	{
		s=cc-48;
	}
	while(1)
	{
		cc=getchar();
		if(cc>=48&&cc<=57)
		{
			s=s*10+cc-48;
		}
		else
		{
			break;
		}
	}
	if(f==true)
	{
		s=-s;
	}
	return s;
}
bool cmp(int a,int b)
{
	return sz[a]>sz[b];
}
void dfs1(int n1)
{
	sz[n1]=1;
	for(int i=0;i<a[n1].size();i++)
	{
		d[a[n1][i]]=d[n1]+1;
		dfs1(a[n1][i]);
		sz[n1]+=sz[a[n1][i]];
	}
	sort(a[n1].begin(),a[n1].end(),cmp);
	int la=0;
	for(int i=0;i<a[n1].size();i++)
	{
		sa[n1].push_back(la);
		la+=sz[a[n1][i]];
	}
}
void dfs2(int n1)
{
	dfn[n1]=++tot;
	la[n1]=n1;
	for(int i=0;i<a[n1].size();i++)
	{
		if(i==0)
		{
			h[a[n1][i]]=h[n1];
		}
		else
		{
			h[a[n1][i]]=a[n1][i];
		}
		dfs2(a[n1][i]);
	}
}
int main()
{
	for(int i=0;i<18;i++)
	{
		for(int j=(1<<i);j<(1<<(i+1));j++)
		{
			pre[j]=i;
		}
	}
	int T;
	cin>>T;
	while(T--)
	{
		int Q,n=0;
		cin>>Q;
		cin>>p[0]>>w[0];
		for(int i=1;i<=Q;i++)
		{
			opt[i]=read1();
			if(opt[i]==1)
			{
				u[i]=read1();
				v[i]=read1();
				fa[u[i]]=v[i];
				p[u[i]]=read1();
				w[u[i]]=read1();
				n=max(n,u[i]);
			}
			else if(opt[i]==2)
			{
				k[i]=read1();
				s[i]=read1();
			}
			else
			{
				l[i]=read1();
			}
		}
		for(int i=0;i<=n;i++)
		{
			e[i]=true;
			a[i].clear();
			sa[i].clear();
		}
		for(int i=1;i<=Q;i++)
		{
			if(opt[i]==1)
			{
				a[v[i]].push_back(u[i]);
			}
		}
		d[0]=1;
		dfs1(0);
		tot=0;
		dfs2(0);
		int tmp=0;
		for(int i=1;i<=Q;i++)
		{
			if(opt[i]==2)
			{
				int q=k[i];
				while(h[q]!=0&&e[h[q]]==true)
				{
					q=fa[h[q]];
				}
				if(d[q]>d[la[h[q]]])
				{
					q=la[h[q]];
				}
				long long ans=0,sum=s[i],cur=0;
				while(1)
				{
					if(w[q]>s[i])
					{
						ans=ans+s[i]*p[q];
						w[q]-=s[i];
						s[i]=0;
						break;
					}
					else
					{
						ans=ans+w[q]*p[q];
						s[i]-=w[q];
						w[q]=0;
						e[q]=false;
						if(d[q]>d[la[h[q]]])
						{
							la[h[q]]=q;
						}
					}
					if(q==k[i])
					{
						break;
					}
					int j=0;
					for(int u=pre[sa[q].size()];u>=0;u--)
					{
						if((j+(1<<u))<sa[q].size())
						{
							if(dfn[k[i]]>dfn[q]+sa[q][j+(1<<u)])
							{
								j+=(1<<u);
							}
						}
					}
					q=a[q][j];
				}
				printf("%lld %lld\n",sum-s[i],ans);
			}
			else if(opt[i]==3)
			{
				w[l[i]]=0;
			}
		}
	}
	return 0;
}
posted @ 2024-08-05 11:09  D06  阅读(5)  评论(0编辑  收藏  举报