zoukankan      html  css  js  c++  java
  • [POI2015]Pustynia

    [POI2015]Pustynia

    题目大意:

    给定一个长度为(n(nle10^5))的正整数序列(a),每个数都在(1)(10^9)范围内,告诉你其中(s)个数,并给出(m)条信息,每条信息包含三个数(l,r,k)以及接下来(k(sum kle3 imes10^5))个正整数,表示(a_{lsim r})里这(k)个数中的任意一个都严格大于剩下(r-l+1-k)个数中的任意一个数。

    请任意构造出一组满足条件的方案,或者判断无解。

    思路:

    考虑差分约束,若一个点(u)大于另一个点(v),则连一条从(v)(u)的新边。若存在环则说明无解,否则在DAG上DP即可。

    但是直接暴力连边时空复杂度都不对,因此我们可以考虑拆点,将(r-l+1-k)个点全部连向一个新的点(t),边权为(0),在从(t)连向(k)个新点,边权为(1)。这样虽然比前面的暴力做法优,但还是不能通过这道题目。

    由于我们要连的(r-l+1-k)个点中,有许多点都是相邻的,因此我们可以将这些点拆成至多(k+1)个区间,用线段树优化连边即可。

    源代码:

    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<algorithm>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=1e5+1,lim=1e9,V=5e5+1;
    struct Edge {
    	int to,w;
    };
    std::vector<Edge> e[V];
    bool vis[V];
    int ind[V],d[V],dis[V],tot;
    inline void add_edge(const int &u,const int &v,const int &w) {
    	e[u].push_back((Edge){v,w});
    	ind[v]++;
    }
    class SegmentTree {
    	#define _left <<1
    	#define _right <<1|1
    	#define mid ((b+e)>>1)
    	private:
    		int id[V<<2];
    	public:
    		void build(const int &p,const int &b,const int &e) {
    			if(b==e) {
    				id[p]=b;
    				return;
    			}
    			id[p]=++tot;
    			build(p _left,b,mid);
    			build(p _right,mid+1,e);
    			add_edge(id[p _left],id[p],0);
    			add_edge(id[p _right],id[p],0);
    		}
    		void link(const int &p,const int &b,const int &e,const int &l,const int &r,const int &x) {
    			if(b==l&&e==r) {
    				add_edge(id[p],x,0);
    				return;
    			}
    			if(l<=mid) link(p _left,b,mid,l,std::min(mid,r),x);
    			if(r>mid) link(p _right,mid+1,e,std::max(mid+1,l),r,x);
    		}
    	#undef _left
    	#undef _right
    	#undef mid
    };
    SegmentTree t;
    inline void kahn() {
    	static std::queue<int> q;
    	for(register int i=1;i<=tot;i++) {
    		if(!ind[i]) {
    			dis[i]=d[i]?:1;
    			q.push(i);
    		}
    	}
    	while(!q.empty()) {
    		const int &x=q.front();
    		vis[x]=true;
    		for(unsigned i=0;i<e[x].size();i++) {
    			const int &y=e[x][i].to,&w=e[x][i].w;
    			if(d[y]) {
    				if(d[y]<dis[x]+w) throw 0;
    				dis[y]=d[y];
    			} else {
    				dis[y]=std::max(dis[y],dis[x]+w);
    				if(dis[y]>lim) throw 0;
    			}
    			if(!--ind[y]) q.push(y);
    		}
    		q.pop();
    	}
    	for(register int i=1;i<=tot;i++) {
    		if(!vis[i]) throw 0;
    	}
    }
    int main() {
    	const int n=tot=getint(),s=getint(),m=getint();
    	t.build(1,1,n);
    	for(register int i=0;i<s;i++) {
    		const int p=getint();
    		dis[p]=d[p]=getint();
    	}
    	for(register int i=0;i<m;i++) {
    		const int l=getint(),r=getint(),k=getint();
    		tot++;
    		int last=l;
    		for(register int i=0;i<k;i++) {
    			const int x=getint();
    			add_edge(tot,x,1);
    			if(x-1>=last) t.link(1,1,n,last,x-1,tot);
    			last=x+1;
    		}
    		if(r>=last) t.link(1,1,n,last,r,tot);
    	}
    	try {
    		kahn();
    	} catch(...) {
    		puts("NIE");
    		return 0;
    	}
    	puts("TAK");
    	for(register int i=1;i<=n;i++) {
    		printf("%d%c",dis[i]," 
    "[i==n]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    MVC传递数据的方式
    c#面向对象的多态
    使用扩展方法创建 HTML Helper
    了解视图、视图数据和 HTML Helper
    十种技能方法提高IT人薪酬
    ASP.net 2.0:系统优化
    第一个简单的MVC页面
    用户体验时代到来,功能不再重要
    关于SQL递归优化
    web(2)
  • 原文地址:https://www.cnblogs.com/skylee03/p/9580650.html
Copyright © 2011-2022 走看看