zoukankan      html  css  js  c++  java
  • 6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

    LINK:Decompose

    avatar
    avatar
    avatar

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

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

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

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

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

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

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

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

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

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

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

    一个细节:叶子节点可以直接列成(Lcdot 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;
    }
    
  • 相关阅读:
    JavaScript -- 条件语句和循环语句
    xpath的|
    Pythonic
    4k图片爬取+中文乱码
    xpath-房价爬取
    (.*?)实验室
    模块的循环导入
    bs4-爬取小说
    糗图-图片爬取
    re实战记录
  • 原文地址:https://www.cnblogs.com/chdy/p/13046809.html
Copyright © 2011-2022 走看看