zoukankan      html  css  js  c++  java
  • 「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("");
    	}
    }
    
  • 相关阅读:
    操作系统(一) 操作系统的概念
    数据结构(六) 排序
    数据结构(五) 查找和哈希表
    数据结构(三) 树和二叉树,以及Huffman树
    数据库简述(以MySQL为例)
    Java中的UDP应用
    Java线程池应用
    Java定时器应用
    JavaSE项目之聊天室swing版
    用LinkedList集合演示栈和队列的操作
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14406118.html
Copyright © 2011-2022 走看看