zoukankan      html  css  js  c++  java
  • bzoj4383 [POI2015]Pustynia 拓扑排序+差分约束+线段树优化建图

    题目传送门

    https://lydsy.com/JudgeOnline/problem.php?id=4383

    题解

    暴力的做法显然是把所有的条件拆分以后暴力建一条有向边表示小于关系。

    因为不存在零环,所以随后可以用拓扑排序来解决。


    考虑如何优化。

    第一个优化比较显而易见,对于一个条件,新建一个虚点,连向所有给出的点。

    第二个是,我们可以发现,给定这 (k) 个点以后,实际上需要建的边是从最多 (k + 1) 个区间中引出的,所以可以考虑线段树优化建图。

    然后就可以和上面一样的,因为不存在零环,所以随后可以用拓扑排序来解决。

    然后这样的时间复杂度是 (O((m+sum k)log n))


    这似乎是我第一次写线段树优化建图呢~虽然一年前就已经学过了,但是一直没写过。

    #include<bits/stdc++.h>
    
    #define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
    #define dbg(...) fprintf(stderr, __VA_ARGS__)
    #define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define fi first
    #define se second
    #define pb push_back
    
    template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
    template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
    
    typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
    
    template<typename I> inline void read(I &x) {
    	int f = 0, c;
    	while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
    	x = c & 15;
    	while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
    	f ? x = -x : 0;
    }
    
    const int N = 100000 * 6 + 7;
    const int M = 100000 * (4 + 3 + 17 + 17) + 7;
    
    #define lc o << 1
    #define rc o << 1 | 1
    
    int n, ns, m, nod;
    int dp[N], nd[N], idg[N], pre[N], rel[N], tmp[N], q[N];
    
    struct Edge { int to, ne, w; } g[M]; int head[N], tot;
    inline void addedge(int x, int y, int z) { g[++tot].to = y, g[tot].w = z, g[tot].ne = head[x], head[x] = tot; }
    inline void adde(int x, int y, int z) { addedge(x, y, z), addedge(y, x, z); }
    
    inline void add_e(int x, int y, int z) { ++idg[y], addedge(x, y, z); }
    
    inline void build(int o, int L, int R) {
    	if (L == R) return (void)(rel[L] = o, pre[o] = L);
    	int M = (L + R) >> 1;
    	add_e(lc, o, 0), build(lc, L, M);
    	add_e(rc, o, 0), build(rc, M + 1, R);
    }
    inline void addi(int o, int L, int R, int l, int r, int x) {
    //	dbg("o = %d, L = %d, R = %d, l = %d, r = %d, x = %d
    ", o, L, R, l, r, x);
    	if (l <= L && R <= r) return add_e(o, x, 1);
    	int M = (L + R) >> 1;
    	if (l <= M) addi(lc, L, M, l, r, x);
    	if (r > M) addi(rc, M + 1, R, l, r, x);
    }
    
    inline void work() {
    	int hd = 0, tl = 0;
    	for (int i = 1; i <= nod; ++i) if (idg[i] == 0) q[++tl] = i, smax(dp[i], 1);
    	while (hd < tl) {
    		int x = q[++hd];
    //		if (dp[x] >= n) dbg("******* x = %d, dp[x] = %d, nd[x] = %d
    ", x, dp[x], nd[x]);
    		if (nd[x]) {
    			if (dp[x] > nd[x]) {
    				puts("NIE");
    				return;
    			} else dp[x] = nd[x];
    		}
    		for fec(i, x, y) {
    			smax(dp[y], dp[x] + g[i].w);
    			if (!--idg[y]) q[++tl] = y;
    		}
    	}
    	for (int i = 1; i <= n; ++i) if (!dp[rel[i]] || dp[rel[i]] > 1e9) {
    		puts("NIE");
    		return;
    	}
    	puts("TAK");
    	for (int i = 1; i <= n; ++i) printf("%d%c", dp[rel[i]], " 
    "[i == n]);
    }
    
    inline void init() {
    	read(n), read(ns), read(m);
    	int x, y;
    	build(1, 1, n);
    	nod = n << 2;
    	for (int i = 1; i <= ns; ++i) read(x), read(y), dp[rel[x]] = nd[rel[x]] = y;
    	for (int i = 1; i <= m; ++i) {
    		int l, r, k;
    		read(l), read(r), read(k);
    		++nod;
    		for (int i = 1; i <= k; ++i) {
    			read(tmp[i]);
    			add_e(nod, rel[tmp[i]], 0);
    			if (i == 1) tmp[i] > l ? addi(1, 1, n, l, tmp[i] - 1, nod) : (void)0;
    			else tmp[i] - tmp[i - 1] > 1 ? addi(1, 1, n, tmp[i - 1] + 1, tmp[i] - 1, nod) : (void)0;
    		}
    		if (tmp[k] != r) addi(1, 1, n, tmp[k] + 1, r, nod);
    	}
    }
    
    int main() {
    #ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    #endif
    	init();
    	work();
    	fclose(stdin), fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    poj 3243 Clever Y(BabyStep GiantStep)
    poj 2417 Discrete Logging
    poj 3481 Double Queue
    hdu 4046 Panda
    hdu 2896 病毒侵袭
    poj 1442 Black Box
    hdu 2815 Mod Tree
    hdu 3065 病毒侵袭持续中
    hdu 1576 A/B
    所有控件
  • 原文地址:https://www.cnblogs.com/hankeke/p/bzoj4383.html
Copyright © 2011-2022 走看看