zoukankan      html  css  js  c++  java
  • Luogu P6852 Mex

    link

    题解

    ([l,r])(mathrm{mex}) 值为 (val) 时, (0,1,cdots,val-1) 位置一定在 ([l,r]) 中 ,(val) 位置一定不在 ([l,r]) 中。
    (x) 可以选的位置集合 (S(x) = igcaplimits_{val_i = x} overline{[l_i,r_i]} cap igcaplimits_{val_i > x}[l_i,r_i] capmathbf{N})
    如果 (S(x) = varnothing) 输出 ( exttt{-1})
    从小到大枚举 (x) ,可以用一个数组 (st)(S(x)) 的元素。
    考虑 (igcaplimits_{val_i > x}[l_i,r_i] subseteq igcaplimits_{val_i > x+1}[l_i,r_i]) ,也就是说,设 ([L_x,R_x] = igcaplimits_{val_i > x}[l_i,r_i]) ,则 (L_{x+1} leq L_x leq R_x leq R_{x+1})
    又想到 (igcaplimits_{val_i = x} overline{[l_i,r_i]}) 是互不交的,所以处理完 (x-1) ,开始处理 (x) 的时候,设 (T = [L_x,L_{x-1}) cap (R_{x-1},R_x] capmathbf{N}) ,先在 (st) 中加入 (T cap overline{igcaplimits_{val_i = x} overline{[l_i,r_i]}}) ,然后在 (st) 中随便选一个元素作为 (x) 的位置,并删去这个元素,再在 (st) 中加入 (T cap igcaplimits_{val_i = x} overline{[l_i,r_i]}) 。注意 (st = varnothing) 的时候输出 ( exttt{-1}) 。总复杂度为 (O(n+m))(具体看代码)

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define MAX_N (500000 + 5)
    #define MAX_M (500000 + 5)
    using std::max;
    using std::min;
    
    int n, m;
    struct Interval {
    	int l, r;
    } a[MAX_N], b[MAX_N];
    int c[MAX_N];
    int st[MAX_N], top;
    int ans[MAX_N];
    
    int Read() {
    	int res = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) ch = getchar();
    	while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar();
    	return res;
    }
    
    int main() {
    	n = Read(), m = Read();
    	int l, r, val;
    	for (int i = 0; i <= n; ++i) {
    		a[i].l = 0;
    		a[i].r = n;
    		b[i].l = n + 1;
    		b[i].r = -1;
    	}
    	for (int i = 1; i <= m; ++i) {
    		l = Read(), r = Read(), val = Read();
    		if (val) {
    			a[val - 1].l = max(a[val - 1].l, l);
    			a[val - 1].r = min(a[val - 1].r, r);
    			b[val].l = min(b[val].l, l);
    			b[val].r = max(b[val].r, r);
    			if (a[val - 1].l > a[val - 1].r) {
    				printf("-1");
    				return 0;
    			}
    		}
    		else {
    			++c[l];
    			--c[r + 1];
    		}
    	}
    	bool flag = 0;
    	for (int i = 0; i <= n; ++i) {
    		if (i) c[i] += c[i - 1];
    		if (!c[i]) flag = 1;
    	}
    	if (!flag) {
    		printf("-1");
    		return 0;
    	}
    	for (int i = n - 1; ~i; --i) {
    		a[i].l = max(a[i].l, a[i + 1].l);
    		a[i].r = min(a[i].r, a[i + 1].r);
    		if (a[i].l > a[i].r) {
    			printf("-1");
    			return 0;
    		}
    	}
    	for (int i = a[0].l; i <= a[0].r; ++i) {
    		if (c[i]) continue;
    		st[++top] = i;
    	}
    	if (!top) {
    		printf("-1");
    		return 0;
    	}
    	ans[st[top--]] = 0;
    	for (int i = a[0].l; i <= a[0].r; ++i) {
    		if (!c[i]) continue;
    		st[++top] = i;
    	}
    	for (int i = 1; i <= n; ++i) {
    		if (b[i].l <= a[i].l && a[i].r <= b[i].r) {
    			printf("-1");
    			return 0;
    		}
    		for (int j = a[i].l; j < a[i - 1].l; ++j)
    			if (j < b[i].l || b[i].r < j) st[++top] = j;
    		for (int j = a[i].r; j > a[i - 1].r; --j)
    			if (j < b[i].l || b[i].r < j) st[++top] = j;
    		if (!top) {
    			printf("-1");
    			return 0;
    		}
    		ans[st[top--]] = i;
    		for (int j = a[i].l; j < a[i - 1].l; ++j)
    			if (b[i].l <= j && j <= b[i].r) st[++top] = j;
    		for (int j = a[i].r; j > a[i - 1].r; --j)
    			if (b[i].l <= j && j <= b[i].r) st[++top] = j;
    	}
    	for (int i = 0; i <= n; ++i)
    		printf("%d ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    java设计模式----代理模式
    其他技术----nginx开光
    Less的使用
    C++ 引用和指针
    leetcode 220 Contains Duplicate
    python网络数据采集1
    404
    前端知识点
    tcl自动生成fifo empty checker
    漫话:如何给女朋友解释什么是"大案牍术"?
  • 原文地址:https://www.cnblogs.com/kcn999/p/13887429.html
Copyright © 2011-2022 走看看