6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

LINK:Decompose

6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

看起来很难 实际上也很难 考验选手的dp 树链剖分 矩阵乘法的能力。

容易列出dp方程 暴力dp 期望得分28.

对于链的情况 容易发现dp方程可以转矩阵乘法 然后利用线段树维护矩阵即可。

这个矩阵很容易列出这里不再赘述。

对于100分 容易想到动态dp模型 LCT写动态dp是万万不能的。

而且这道题的dp方程和其他儿子也有些关系。

考虑树链剖分 然后分别计算轻儿子和重儿子的贡献。

让重儿子利用矩阵来进行转移 轻儿子当做常数.

这样每次修改的时候 修改的节点最多只有logn个.

用set维护需要维护的东西即可。

剩下的就是树链剖分型动态dp的套路 每次利用链顶的矩阵信息更新下一个节点即可。

一个细节:叶子节点可以直接列成\(L\cdot L\)的矩阵 只有第一个元素有值 这样更容易实现。

一个细节:可能矩阵乘法出来的值和原来的值不尽相同 此时考虑更新set的时候利用原来信息更新 然后更新原来信息即可。

思维难度:高 代码难度:极高。

const ll MAXN=100010;
ll n,Q,L,len,id;
ll top[MAXN],pos[MAXN],dfn[MAXN],fa[MAXN],c[MAXN],sum[MAXN];
ll a[MAXN][5],d[MAXN],son[MAXN],sz[MAXN],f[MAXN][5],w[MAXN];
ll lin[MAXN],ver[MAXN<<1],nex[MAXN<<1];
multiset<ll>s[MAXN][4];
struct wy
{
ll b[5][5];
ll l,r;
wy(){l=r=0;rep(1,L,i)rep(1,L,j)b[i][j]=-INF;}
wy friend operator +(wy a,wy b)
{
wy c;c.l=b.l;c.r=a.r;
rep(1,L,i)rep(1,L,j)rep(1,L,k)
c.b[i][j]=max(c.b[i][j],a.b[i][k]+b.b[k][j]);
return c;
}
}t[MAXN<<2];
inline void add(ll x,ll y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(ll x,ll father)
{
d[x]=d[father]+1;fa[x]=father;sz[x]=1;
rep(2,L,j)f[x][j]=-INF;w[x]=-INF;
f[x][1]=a[x][1];ll ans=0;
go(x)if(tn!=father)
{
dfs(tn,x);
if(sz[tn]>sz[son[x]])son[x]=tn;
sz[x]+=sz[tn];
rep(2,L,j)f[x][j]=max(f[x][j]+w[tn],f[tn][j-1]+a[x][j]+ans);
ans+=w[tn];
}
f[x][1]+=ans;
rep(1,L,j)w[x]=max(w[x],f[x][j]);
go(x)if(tn!=father&&tn!=son[x])
rep(1,L-1,j)s[x][j].insert(f[tn][j]-w[tn]);
sum[x]=ans-w[son[x]];
}
inline void dp(ll x,ll father)
{
top[x]=father;dfn[x]=++id;pos[id]=x;c[father]=x;
if(!son[x])return;
dp(son[x],father);
go(x)if(tn!=son[x]&&tn!=fa[x])dp(tn,tn);
}
inline void build(ll p,ll l,ll r)
{
l(p)=l;r(p)=r;
if(l==r)
{
ll x=pos[l];
if(sz[x]==1)
{
rep(1,L,i)rep(1,L,j)t[p].b[i][j]=-INF;
t[p].b[1][1]=a[x][1];
}
else
{
rep(1,L,i)t[p].b[i][1]=a[x][1]+sum[x];
ll flag=s[x][1].size();
rep(2,L,j)
{
ll ww=flag?(*--s[x][j-1].end()):-INF;
rep(1,L,i)t[p].b[i][j]=a[x][j]+sum[x]+ww;
t[p].b[j-1][j]-=ww;
}
}
return;
}
ll mid=(l+r)>>1;
build(zz,l,mid);
build(yy,mid+1,r);
t[p]=t[yy]+t[zz];
}
inline void change(ll p,ll x)
{
if(l(p)==r(p))
{
ll x=pos[l(p)];
if(sz[x]==1)
{
rep(1,L,i)rep(1,L,j)t[p].b[i][j]=-INF;
t[p].b[1][1]=a[x][1];
}
else
{
rep(1,L,i)t[p].b[i][1]=a[x][1]+sum[x];
ll flag=s[x][1].size();
rep(2,L,j)
{
//cout<<s[x][j-1].size()<<endl;
ll ww=flag?(*(--s[x][j-1].end())):-INF;
rep(1,L,i)t[p].b[i][j]=a[x][j]+sum[x]+ww;
t[p].b[j-1][j]-=ww;
//cout<<t[p].b[j-1][j]<<endl;
}
//rep(1,L,i){rep(1,L,j)cout<<t[p].b[i][j]<<' ';cout<<endl;}
}
return;
}
ll mid=(l(p)+r(p))>>1;
if(x<=mid)change(zz,x);
else change(yy,x);
t[p]=t[yy]+t[zz];
}
inline wy ask(ll p,ll l,ll r)
{
if(l<=l(p)&&r>=r(p))return t[p];
ll mid=(l(p)+r(p))>>1;
if(l>mid)return ask(yy,l,r);
if(r<=mid)return ask(zz,l,r);
return ask(yy,l,r)+ask(zz,l,r);
}
inline void Tchange(ll x)
{
ll fx=top[x];
while(fx!=1)
{
change(1,dfn[x]);
wy w1=ask(1,dfn[fx],dfn[c[fx]]);
x=fa[fx];//修改x.
ll cnt1=-INF;
rep(1,L,i)cnt1=max(cnt1,w1.b[1][i]);
sum[x]=sum[x]-w[fx]+cnt1;
fep(L-1,1,i)
{
s[x][i].erase(s[x][i].find(f[fx][i]-w[fx]));
s[x][i].insert(w1.b[1][i]-cnt1);
f[fx][i]=w1.b[1][i];
}
w[fx]=cnt1;fx=top[x];
}
change(1,dfn[x]);
wy ww=ask(1,dfn[1],dfn[c[1]]);ll ans=-INF;
rep(1,L,i)
{
ans=max(ans,ww.b[1][i]);
//cout<<ww.b[1][i]<<' ';
}
//puts("");
putl(ans);
}
signed main()
{
freopen("decompose.in","r",stdin);
freopen("decompose.out","w",stdout);
get(n);get(Q);get(L);
rep(2,n,i)add(read(),i);
rep(1,n,i)rep(1,L,j)get(a[i][j]);
dfs(1,0);dp(1,1);
build(1,1,n);
//wy ww=ask(1,dfn[1],dfn[c[1]]);ll ans=-INF;
//rep(1,L,i)ans=max(ans,ww.b[1][i]),cout<<ww.b[1][i]<<' ';
//puts("");putl(ans);
rep(1,Q,i)
{
ll get(x);
rep(1,L,j)get(a[x][j]);
Tchange(x);
}
return 0;
}
上一篇:吴恩达-coursera-机器学习-week1


下一篇:im消息丢失插件