蒟蒻求助二分答案
查看原帖
蒟蒻求助二分答案
128591
Refined_heart楼主2021/8/26 11:04

面向数据发现答案略大……从十分调到80实在不知道哪里错了 求助/kel

大概是二分一个时间之后每个军队倍增跳到第二层节点然后把可以继续往其他节点的点给提出来,贪心解决没有被覆盖的点

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+10;
int n,m,f[N][20],s[N][20],Vis[N],sum[N],vp[N];
vector<int>G[N],V[N],Leaf;
int pos[N],cpos[N],dfn[N],idfn[N];
int dfstime,tr[N],ctm[N],siz[N],vis[N];
int anc[N];
vector<int>Tp[N];
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*w;
}
inline bool cmp(int x,int y){return x>y;}
void link(int u,int v,int w){
	G[u].push_back(v);
	G[v].push_back(u);
	V[u].push_back(w);
	V[v].push_back(w);
}
void dfs(int x,int fa,int w){
	f[x][0]=fa;s[x][0]=w;
	for(int i=1;i<20;++i)f[x][i]=f[f[x][i-1]][i-1];
	for(int i=1;i<20;++i)s[x][i]=s[x][i-1]+s[f[x][i-1]][i-1];
	idfn[dfn[x]=++dfstime]=x;siz[x]=1;
	for(int i=0;i<(int)G[x].size();++i){
		int v=G[x][i];
		int w=V[x][i];
		if(v==fa)continue;
		dfs(v,x,w);siz[x]+=siz[v];
	}
}
bool check(int Time){
//	printf("Time:%lld:\n",Time);
	multiset<int>S;
	vector<int>U;
	for(int i=1;i<=n+1;++i)vis[i]=Vis[i]=sum[i]=vp[i]=0,Tp[i].clear();
	for(int i=1;i<=m;++i)cpos[i]=pos[i],ctm[i]=0;
	for(int i=1;i<=m;++i)
		for(int j=19;~j;--j)
			if(f[cpos[i]][j]&&ctm[i]+s[cpos[i]][j]<=Time&&f[f[cpos[i]][j]][0]>=1)ctm[i]+=s[cpos[i]][j],cpos[i]=f[cpos[i]][j];
//	for(int i=1;i<=m;++i)cout<<cpos[i]<<" "<<ctm[i]<<endl;
//	puts("Resttime:");
	for(int i=1;i<=m;++i){
		if(f[cpos[i]][0]!=1)continue;
		int Tm=Time-ctm[i]-s[cpos[i]][0];
//		cout<<Tm<<" ";
		Tp[cpos[i]].push_back(Tm);
	}
	for(int i=1;i<=m;++i){
		if(f[cpos[i]][0]!=1)continue;
		vp[cpos[i]]=1;
		if(vis[cpos[i]])continue;
		vis[cpos[i]]=1;
		sort(Tp[cpos[i]].begin(),Tp[cpos[i]].end(),cmp);
	}
	for(int i=1;i<=n+1;++i)vis[i]=0;
	for(int i=1;i<=m;++i){
		if(f[cpos[i]][0]==1)continue;
		int l=dfn[cpos[i]];
		int r=dfn[cpos[i]]+siz[cpos[i]]-1;
		vis[l]++;
		vis[r+1]--;
	}
	for(int i=1;i<=n+1;++i)vis[i]+=vis[i-1];
	for(int i=1;i<=n;++i)if(vis[i])sum[i]=1;
	for(int i=1;i<=n;++i)sum[i]+=sum[i-1];
//	puts("");
//	for(int i=1;i<=n;++i)cout<<vis[i]<<" ";
//	cout<<endl;
//	puts("Anc:");
	for(auto v:Leaf){
//		if(!vis[dfn[v]])cout<<anc[v]<<endl;
		if(!vis[dfn[v]]){
			if(Vis[anc[v]])continue;
			if(vp[anc[v]]==1){
				vp[anc[v]]=2;
				Tp[anc[v]].pop_back();
				continue;
			}
			if(vp[anc[v]]==2)continue;
			S.insert(s[anc[v]][0]);
			Vis[anc[v]]=1;
		}
	}
//	puts("SET:");
//	for(auto v:S)cout<<v<<endl;
	if(S.empty())return true;
	for(int i=1;i<=m;++i){
		if(f[cpos[i]][0]!=1)continue;
		int Siz=(int)Tp[cpos[i]].size();
		for(int ts=0;ts<Siz;++ts){
			int bk=Tp[cpos[i]].back();
//			if(bk<=0)break;
			Tp[cpos[i]].pop_back();
			U.push_back(bk);
		}
	}
	if(U.empty())return false;
	sort(U.begin(),U.end());
//	puts("U:");
//	for(auto v:U)cout<<v<<endl;
//	puts("Deal:");
	int posb=0,SU=(int)U.size();
	while(!S.empty()&&posb<SU){
		int v=*S.begin();
//		int cost=s[v][0];
//		cout<<cost<<endl;
//		cout<<v<<endl;
		while(posb<SU&&U[posb]<v)++posb;
		if(posb==SU)return false;
		posb++;
		multiset<int>::iterator it=S.find(v);
		S.erase(it);
	}
//	puts("SET:");
//	for(auto v:S)cout<<v<<endl;
//	puts("End.");
	return S.empty();
}
signed main(){
 	freopen("357.in","r",stdin);
 	freopen("357.out","w",stdout);
//	puts("?");
	n=read();
	for(int i=1;i<n;++i){
		int u=read(),v=read(),w=read();
		link(u,v,w);
	}
	dfs(1,0,0);
//	cout<<dfn[7]<<" "<<siz[7]<<" "<<dfn[9]<<endl;
	m=read();
	for(int i=1;i<=m;++i)pos[i]=read();
	for(int i=1;i<=n;++i)if(siz[i]==1)Leaf.push_back(i);
//	for(auto v:Leaf)cout<<v<<endl;
	for(auto v:Leaf){
		int PP=v;
		for(int i=19;~i;--i)
			if(f[PP][i]&&f[f[PP][i]][0]>=1)
				PP=f[PP][i];
		anc[v]=PP;
	}
	int l=0,r=100000000000000ll;
	int ans=-1;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid))ans=mid,r=mid-1;
		else l=mid+1;
//		puts("");
	}
	cout<<ans<<endl;
	return 0;
}
// smaller
2021/8/26 11:04
加载中...