救救孩子吧,孩子快疯了,ddp 92分求调
查看原帖
救救孩子吧,孩子快疯了,ddp 92分求调
1024338
Le0Chan楼主2023/10/27 11:05

rt,在判无解上出了问题。算法是 ddp,但没有利用最小点覆盖=全-最大点独立,直接 dp。强制选,将 gx,0g_{x,0} 赋 infinf,强制不选,将 gx,1g_{x,1} 赋 infinf。判无解1:两点在一条边两端且都强制不选,判无解2:答案超过 101010^{10},因为点数 10510^5,点权 10510^5。

#include <bits/stdc++.h>
using namespace std;

#define LL long long
#define int long long
#define pii pair<int,int>

const int N=1e5+5;
const LL inf=1e18;

int n,m,df,cnt; 
int dep[N],f[N],son[N],siz[N],top[N],dfn[N],idfn[N],ed[N],a[N],g[N][2],dp[N][2],head[N];
string s;
map<pii,int> ap;

struct node{
	int to,ne;
}e[N<<1];

inline void dfs(int x,int fa){
	dep[x]=dep[fa]+1;
	f[x]=fa;
	siz[x]=1;
	for(int i=head[x];i;i=e[i].ne){
		int y=e[i].to;
		if(y!=fa){
			dfs(y,x);
			siz[x]+=siz[y];
			if(siz[y]>siz[son[x]]){
				son[x]=y;
			}
		}
	}
}

inline void dfs2(int x,int tp){
	top[x]=tp;
	dfn[x]=++df;
	idfn[df]=x;
	int sn=0;
	for(int i=head[x];i;i=e[i].ne){
		int y=e[i].to;
		if(y!=f[x]) sn++;
	}
	if(!sn) ed[tp]=x;
	g[x][1]=a[x];
	if(son[x]){
		dfs2(son[x],tp);
		dp[x][1]+=min(dp[son[x]][1],dp[son[x]][0]);
		dp[x][0]+=dp[son[x]][1];
	}
	for(int i=head[x];i;i=e[i].ne){
		int y=e[i].to;
		if(y!=f[x]&&y!=son[x]){
			dfs2(y,y);
			g[x][0]+=dp[y][1];
			g[x][1]+=min(dp[y][0],dp[y][1]);
		}
	}
	dp[x][0]+=g[x][0];
	dp[x][1]+=g[x][1];
}

struct mat{
	LL at[2][2];
	mat(){at[0][0]=at[0][1]=at[1][0]=at[1][1]=inf;}
	void bs(){at[0][0]=at[0][1]=0;at[1][0]=at[1][1]=4e18;}
	void prin(){cout<<at[0][0]<<" "<<at[0][1]<<"\n"<<at[1][0]<<" "<<at[1][1]<<"\n";}
};

mat operator*(mat a,mat b){
	mat c;
	c.at[0][0]=min(a.at[0][0]+b.at[0][0],a.at[0][1]+b.at[1][0]);
	c.at[0][1]=min(a.at[0][0]+b.at[0][1],a.at[0][1]+b.at[1][1]);
	c.at[1][0]=min(a.at[1][0]+b.at[0][0],a.at[1][1]+b.at[1][0]);
	c.at[1][1]=min(a.at[1][0]+b.at[0][1],a.at[1][1]+b.at[1][1]);
	return c;
} 

struct seg{
	mat t[N<<2],pre[N<<2];
	inline void pp(int p){t[p]=t[p<<1|1]*t[p<<1];}
	inline void build(int p,int l,int r){
		if(l==r){
			t[p].at[0][1]=g[idfn[l]][1];
			t[p].at[1][0]=g[idfn[l]][0];
			t[p].at[1][1]=g[idfn[l]][1];
			pre[p]=t[p];
			return ;
		}
		int mid=l+r>>1;
		build(p<<1,l,mid);
		build(p<<1|1,mid+1,r);
		pp(p);
	}
	inline void md(int p,int l,int r,int x,int k){
		if(l==r){
			if(k==1){
				t[p].at[0][0]=t[p].at[1][0]=inf;
				t[p].at[0][1]=t[p].at[1][1]=g[idfn[l]][1];
			}
			else if(k==0){
				t[p].at[0][0]=t[p].at[0][1]=t[p].at[1][1]=inf;
				t[p].at[1][0]=g[idfn[l]][0];
			}
			else{
				t[p].at[0][0]=inf;
				t[p].at[1][0]=g[idfn[l]][0];
				t[p].at[0][1]=t[p].at[1][1]=g[idfn[l]][1];
			}
			return ;
		}
		int mid=l+r>>1;
		if(x<=mid) md(p<<1,l,mid,x,k);
		else md(p<<1|1,mid+1,r,x,k);
		pp(p);
	}
	inline void topre(int p,int l,int r,int x){
		if(l==r){
			t[p]=pre[p];
			g[idfn[l]][0]=pre[p].at[1][0];
			g[idfn[l]][1]=pre[p].at[0][1];
			return ;
		}
		int mid=l+r>>1;
		if(x<=mid) topre(p<<1,l,mid,x);
		else topre(p<<1|1,mid+1,r,x);
		pp(p);
	}
	inline mat query(int p,int l,int r,int ql,int qr){
		if(l>=ql&&r<=qr){
			return t[p];
		}
		int mid=l+r>>1;
		if(qr<=mid) return query(p<<1,l,mid,ql,qr);
		if(ql>mid) return query(p<<1|1,mid+1,r,ql,qr);
		return query(p<<1|1,mid+1,r,ql,qr)*query(p<<1,l,mid,ql,qr);
	}
}sg;

inline void ct(){
	dfs(1,0);
	dfs2(1,1);
	sg.build(1,1,n);
}

inline mat getdp(int x){
	mat bs;bs.bs();
	return bs*sg.query(1,1,n,dfn[x],dfn[ed[x]]);
}

inline void mp(int x,int k){
	int tm=x;
	while(1){
		auto as=getdp(top[x]);
		g[f[top[x]]][0]-=as.at[0][1];
		g[f[top[x]]][1]-=min(as.at[0][1],as.at[0][0]);
		sg.md(1,1,n,dfn[x],tm==x?k:-1);
		as=getdp(top[x]);
		
		g[f[top[x]]][0]+=as.at[0][1];
		g[f[top[x]]][1]+=min(as.at[0][1],as.at[0][0]);
		if(top[x]==1) break;
		x=f[top[x]];
	}
}

inline void pre(int x){
	while(1){
		sg.topre(1,1,n,dfn[x]);
		if(top[x]==1) break;
		x=f[top[x]];
	}
}

inline void modify(int a,int x,int b,int y){
	mp(a,x);
	mp(b,y);
	auto as=getdp(1);
	LL minn=min(as.at[0][1],as.at[0][0]);
	if(minn>1e10) cout<<"-1\n";
	else cout<<minn<<"\n";
	pre(a);
	pre(b);
}

inline void add(int x,int y){
	e[++cnt]=(node){y,head[x]};
	head[x]=cnt;	
}

signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n>>m>>s;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1,x,y;i<n;i++){
		cin>>x>>y;
		add(x,y);
		add(y,x);
		ap[{x,y}]=ap[{y,x}]=1;
	}
	ct();
	while(m--){
		int a,x,b,y;
		cin>>a>>x>>b>>y;
		if(!x&&!y&&ap[{x,y}]){
			cout<<"-1\n";
			return 0;
		}
		modify(a,x,b,y);
	}
	return 0;
}

2023/10/27 11:05
加载中...