「ROI 2019 Day1」运输 20/19

「ROI 2019 Day1」运输 20/19

题目大意:

给定一个带权(DAG)(1)为起始点,给定小常数(p)

每次查询一个点(u),一个权值(r),问是否存在一条路径(1ldots u),其长度(x)满足(rleq xleq frac{p}{p-1}cdot r)

转换一下,(dp)每个点是否存在(r),那么对于路径的权值(x),合法的(r)即为([frac{p-1}{p}cdot x,x])

对于任意两个区间,如果其相交,则可以合并,并且用两个区间中最小和最大的(x)来表示这个区间

而不相交的区间最多只有(log_{frac{p}{p-1}} w)段,大概(700)

任意时刻,每个点的(dp)情况可以用(700)段不交的区间表示,转移可以归并数组进行

因此维护(dp)复杂度为(O(mlog_{frac{p}{p-1}} w))常数极小,单次查询复杂度为(O(log log_{frac{p}{p-1}} w))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
char IO;
template <class T=int> T rd(){
	T s=0; int f=0;
	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
	do s=(s<<1)+(s<<3)+(IO^'0');
	while(isdigit(IO=getchar()));
	return f?-s:s;
}

const int N=5e5+10;

int n,m,q,p;
struct Interval{
	ll l,r,x,y;
	Interval(ll a,ll b){ 
		x=a,y=b;
		l=(x*(p-1)+p-1)/p,r=y;
	}
	void Add(ll c){
		x+=c,y+=c;
		l=(x*(p-1)+p-1)/p,r=y;
	}
	bool operator & (const Interval &__) const { return min(r,__.r)>=max(l,__.l)-1; }
	Interval operator + (const Interval &__) const { return Interval(min(x,__.x),max(y,__.y)); }
	bool operator < (const ll &x) const {
		return r<x;
	}
};
vector <Interval> dp[N];

struct Edge{
	int to,nxt; ll w;
} e[N];
int head[N],ecnt;
void AddEdge(int u,int v,ll w){
	e[++ecnt]=(Edge){v,head[u],w};
	head[u]=ecnt;
}
void Trans(vector <Interval> &x,vector <Interval> y,ll c){
	for(auto &i:y) i.Add(c);
	vector <Interval> res;
	int p1=0,p2=0,s1=x.size(),s2=y.size();
	while(p1<s1 || p2<s2) {
		if(p1<s1 && (p2==s2 || x[p1].l<=y[p2].l)) {
			if(res.size() && *res.rbegin()&x[p1]) res[res.size()-1]=*res.rbegin()+x[p1++];
			else res.pb(x[p1++]);
		} else {
			if(res.size() && *res.rbegin()&y[p2]) res[res.size()-1]=*res.rbegin()+y[p2++];
			else res.pb(y[p2++]);
		}
	}
	x=res;
}

int main(){
	rep(kase,1,rd()) {
		n=rd(),m=rd(),q=rd(),p=rd();
		rep(i,1,n) head[i]=ecnt=0;
		rep(i,1,m){
			int u=rd(),v=rd(); ll w=rd<ll>();
			AddEdge(u,v,w);
		}
		rep(i,1,n) dp[i].clear();
		dp[1].pb(Interval(0,0));
		rep(u,1,n) {
			for(int i=head[u];i;i=e[i].nxt) {
				Trans(dp[e[i].to],dp[u],e[i].w);
			}
		}
		while(q--){
			int x=rd(); ll y=rd<ll>();
			auto p=lower_bound(dp[x].begin(),dp[x].end(),y);
			if(p!=dp[x].end() && p->l<=y) putchar('1');
			else putchar('0');
		}
		puts("");
	}
}
原文地址:https://www.cnblogs.com/chasedeath/p/14406118.html