- 赛后独立做出了这道题,开心~
- 在随机数据下,朴素维护已经是一个比较高效的过程了
- 考虑特殊情形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;
}