【倍增】【dp】找宝藏

【题意描述】
给定一个有向无环图,和若干询问,每次询问从一点出发的路径上的边的边权形成的字符串的字典序第k小的长度至少为1的路径的终点。
n , m , q < = 2 e 5 k < = 1 e 9 n,m,q<=2e5,k<=1e9

【思路】

这道题很有意思。我们可以先预处理每个点出发的路径条数,这个可以用dp O ( n + m ) O(n+m) 实现。考虑暴力,我们每次在树上贪心地走。考虑倍增,我们以每个点dp值最大的那个儿子为重儿子。预处理 s o n i , j son_{i,j} 表示沿重边走 2 j 2^j 步的点和 s i , j s_{i,j} 表示向下走 2 j 2^j 步的所有字典序排在重边以前的轻边的方案之和。考虑找到一条答案路径的时间,由于我们走轻边会使方案数至少少一半,所以最多会经过log条轻边和log条重边。每次需要走重边时,我们可以 O ( l o g ) O(log) 倍增,每次需要走轻边时,我们可以 O ( l o g ) O(log) 二分走哪个分支。注意方案数可能很大,可能爆longlong,故方案数需要对一个极大值取min。时间复杂度 O ( n l o g n 2 ) O(nlog^2_n)
代码:

#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=2e5+5;
typedef long long ll;
inline int red(){
    int data=0;bool w=0; char ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return w?-data:data;
}
int n,m,a,b,q,in[N],len[N];
const ll lim=1e15;
vector<int>g[N];
vector<ll>sum[N];
ll dp[N],s[N][19];
inline void cmin(ll&x,const ll&y){(x>y)&&(x=y);}
int son[N][19];
void dfs(int u){
	if(~dp[u])return;int v;dp[u]=0;
	sum[u].resize(len[u]=g[u].size());
	for(int re i=0;i<len[u];i++){
		dfs(v=g[u][i]);
		if(dp[v]>dp[son[u][0]])son[u][0]=v,s[u][0]=dp[u]+1;
		cmin(dp[u]+=dp[v]+1,lim);
		sum[u][i]=dp[u];
	}for(int re i=1;i<18;++i)
		son[u][i]=son[son[u][i-1]][i-1],s[u][i]=min(lim,s[u][i-1]+s[son[u][i-1]][i-1]);
}
int find(int u,int k){
	if(!k)return u;
	for(int re i=17;~i;--i)
		if(s[u][i]<=k&&s[u][i]+dp[son[u][i]]>=k)
			return find(son[u][i],k-s[u][i]);
	int l=0,r=len[u]-1,mid;
	while(l<r)sum[u][mid=(l+r)>>1]<k?l=mid+1:r=mid;
	return find(g[u][l],k-(l-1<0?1:sum[u][l-1]+1));
}
int main(){
	n=red();m=red();
	memset(dp,-1,sizeof(dp[0])*(n+1));
	for(int re i=1;i<=m;i++){
		a=red();b=red();
		g[a].push_back(b);
		in[b]++;
	}for(int re i=1;i<=n;i++)if(!in[i])dfs(i);
	q=red();
	while(q--){
		a=red();b=red();
		if(dp[a]<b){puts("-1");continue;}
		cout<<find(a,b)<<"\n";
	}
}
发布了106 篇原创文章 · 获赞 22 · 访问量 5481

猜你喜欢

转载自blog.csdn.net/weixin_44111457/article/details/102767331