题解:P10599 BZOJ2164 采矿
linruichen · · 题解
题目大意
给定矿点个数
解题思路
看见选择出最大值可以想到 DP,处理链想到树链剖分,及将树进行树链剖分,再用线段树建树,线段树的每个节点存储一个数组
参考代码
#include<bits/stdc++.h>
using namespace std;
long long tou[20010],zui[20010],wei[20010],bian[20010],shen[20010],da[20010],
son[20010],t,b[20010],fa[20010],n,m,B,A,Q,X,Y,p,c[51],d[51];
struct w{
long long x,y;
}a[100010];
struct o{
long long a[51],g[51];
}f[80010],uv[20010];
inline long long Getint()
{
A=((A^B)+B/X+B*X)&Y;
B=((A^B)+A/X+A*X)&Y;
return (A^B)%Q;
}
void ww(long long die,long long ye)
{
fa[die]=ye;
da[die]=1;
for(long long i=b[die];i;i=a[i].y)
if(a[i].x!=ye)
{
shen[a[i].x]=shen[die]+1;
ww(a[i].x,die);
da[die]+=da[a[i].x];
}
for(long long i=b[die];i;i=a[i].y)
if(a[i].x!=ye)
if(da[son[die]]<da[a[i].x])
son[die]=a[i].x;
}
void www(long long die,long long ye)
{
if(son[die])
{
tou[son[die]]=tou[die];
wei[son[die]]=++t;
bian[wei[son[die]]]=son[die];
zui[son[die]]=wei[son[die]];
www(son[die],die);
zui[die]=max(zui[die],zui[son[die]]);
}
for(long long i=b[die];i;i=a[i].y)
if(a[i].x!=ye&&a[i].x!=son[die])
{
tou[a[i].x]=a[i].x;
wei[a[i].x]=++t;
zui[a[i].x]=wei[a[i].x];
bian[wei[a[i].x]]=a[i].x;
www(a[i].x,die);
zui[die]=max(zui[die],zui[a[i].x]);
}
}
void jian(long long k,long long l,long long r)
{
if(l==r)
{
for(long long i=0;i<=m;i++)
f[k].a[i]=uv[bian[l]].a[i],
f[k].g[i]=uv[bian[l]].a[i];
return;
}
long long mid=(l+r)/2;
jian(k*2,l,mid);
jian(k*2+1,mid+1,r);
for(long long i=0;i<=m;i++)
for(long long j=0;j<=i;j++)
f[k].a[i]=max(f[k].a[i],f[k*2].a[j]+f[k*2+1].a[i-j]);
for(long long i=0;i<=m;i++)
f[k].g[i]=max(f[k*2].g[i],f[k*2+1].g[i]);
}
void gai(long long k,long long l,long long r,long long x)
{
if(l==r)
{
for(long long i=0;i<=m;i++)
f[k].a[i]=uv[bian[l]].a[i],
f[k].g[i]=uv[bian[l]].a[i];
return;
}
long long mid=(l+r)/2;
if(x<=mid)gai(k*2,l,mid,x);
if(x>mid)gai(k*2+1,mid+1,r,x);
for(int i=0;i<=m;i++)
f[k].g[i]=f[k].a[i]=0;
for(long long i=0;i<=m;i++)
for(long long j=0;j<=i;j++)
f[k].a[i]=max(f[k].a[i],f[k*2].a[j]+f[k*2+1].a[i-j]);
for(long long i=0;i<=m;i++)
f[k].g[i]=max(f[k*2].g[i],f[k*2+1].g[i]);
}
void qui_f(long long k,long long l,long long r,long long x,long long y)
{
if(x<=l&&r<=y)
{
for(long long i=m;i>=0;i--)
for(long long j=i;j>=0;j--)
c[i]=max(c[i],c[j]+f[k].a[i-j]);
return;
}
long long mid=(l+r)/2;
if(x<=mid)qui_f(k*2,l,mid,x,y);
if(y>mid)qui_f(k*2+1,mid+1,r,x,y);
}
void qui_g(long long k,long long l,long long r,long long x,long long y)
{
if(x<=l&&r<=y)
{
for(long long i=0;i<=m;i++)
d[i]=max(d[i],f[k].g[i]);
return;
}
long long mid=(l+r)/2;
if(x<=mid)qui_g(k*2,l,mid,x,y);
if(y>mid)qui_g(k*2+1,mid+1,r,x,y);
}
void llca(long long x,long long y)
{
long long fx=tou[x],fy=tou[y];
while(fx!=fy)
{
if(shen[fx]<shen[fy])
swap(fx,fy),swap(x,y);
qui_g(1,1,n,wei[fx],wei[x]);
x=fa[fx];
fx=tou[x];
}
if(shen[x]>shen[y])
swap(x,y);
qui_g(1,1,n,wei[x],wei[y]);
}
main()
{
scanf("%lld%lld%lld%lld%lld",&n,&m,&A,&B,&Q);
X=pow(2,16);
Y=pow(2,31)-1;
for(long long i=2;i<=n;i++)
{
long long x;
scanf("%lld",&x);
a[++t].x=x;
a[t].y=b[i];
b[i]=t;
a[++t].x=i;
a[t].y=b[x];
b[x]=t;
}
ww(1,1);
t=0;
tou[1]=1;
wei[1]=++t;
bian[wei[1]]=1;
zui[1]=1;
www(1,1);
for(long long i=1;i<=n;i++)
{
uv[i].a[0]=0;
for(long long j=1;j<=m;j++)
uv[i].a[j]=Getint();
sort(uv[i].a+1,uv[i].a+m+1);
}
jian(1,1,n);
scanf("%lld",&p);
while(p--)
{
long long z;
scanf("%lld",&z);
if(z==0)
{
long long x;
scanf("%lld",&x);
uv[x].a[0]=0;
for(long long j=1;j<=m;j++)
uv[x].a[j]=Getint();
sort(uv[x].a+1,uv[x].a+m+1);
gai(1,1,n,wei[x]);
}
else
{
for(long long i=0;i<=m;i++)
c[i]=d[i]=0;
long long u,v,uu;
scanf("%lld%lld",&u,&v);
uu=fa[u];
if(shen[uu]>=shen[v])
llca(uu,v);
qui_f(1,1,n,wei[u],zui[u]);
long long s=0;
for(long long i=0;i<=m;i++)
s=max(s,c[i]+d[m-i]);
printf("%lld\n",s);
}
}
}