zoukankan      html  css  js  c++  java
  • BZOJ1178或洛谷3626 [APIO2009]会议中心

    BZOJ原题链接

    洛谷原题链接

    第一个问题是经典的最多不相交区间问题,用贪心即可解决。
    主要问题是第二个,求最小字典序的方案。
    我们可以尝试从(1 o n)扫一遍所有区间,按顺序对每一个不会使答案变差的区间都尝试着去填,这样就可以保证方案的字典序最小。
    考虑如果快速判断该区间是否能成为最优解,开头先按右端点从小到大排序,左端点从大到小排序,再去除有包含关系的区间,这样使得讨论更为简单。
    设待插入的区间为([r,l]),该区间左边的第一个已插入的区间的右端点为(L),右边的第一个已插入的区间的左端点为(R)(S[i][j])表示([i,j])间有多少已插入的区间。
    则该区间能插入必须满足(S[L + 1][R - 1] = S[L + 1][r - 1] + S[l + 1][R - 1] + 1)
    对于快速计算(S),我们可以采用倍增的思想,设(ne[x][i])表示第(x)个区间后选择(2^i)个区间的最后一个区间下标,可以使用倍增在(nlogn)内预处理出来。
    维护已插入区间可以使用(C++ STL set)

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<set>
    using namespace std;
    const int N = 2e5 + 10;
    const int M = 18;
    struct dd{
    	int x, y;
    	bool operator < (const dd &b) const
    	{
    		if (!(y ^ b.y))
    			return x > b.x;
    		return y < b.y;
    	}
    };
    dd a[N], b[N];
    int X[N], Y[N], ne[N][M], m, gn;
    set<dd>S;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int lowbod(int x)
    {
    	int l = 1, r = m, mid, an = m + 1;
    	while (l <= r)
    	{
    		mid = (l + r) >> 1;
    		if (X[mid] >= x)
    		{
    			an = mid;
    			r = mid - 1;
    		}
    		else
    			l = mid + 1;
    	}
    	return an;
    }
    inline int calc(int l, int r)
    {
    	int x = lowbod(l);
    	if (x > m || Y[x] > r)
    		return 0;
    	int s = 1;
    	for (int i = gn; ~i; i--)
    		if (ne[x][i] && Y[ne[x][i]] <= r)
    		{
    			s += 1 << i;
    			x = ne[x][i];
    		}
    	return s;
    }
    int main()
    {
    	int i, j, n, l, r, L, R;
    	n = re();
    	for (i = 1; i <= n; i++)
    	{
    		a[i].x = re();
    		a[i].y = re();
    		b[i] = a[i];
    	}
    	sort(b + 1, b + n + 1);
    	for (i = 1; i <= n; i++)
    		if (b[i].x > b[m].x || !m)
    			b[++m] = b[i];
    	for (i = 1; i <= m; i++)
    	{
    		X[i] = b[i].x;
    		Y[i] = b[i].y;
    	}
    	for (i = j = 1; i <= m; i++)
    	{
    		for (; j <= m && b[j].x <= b[i].y; j++);
    		if (j <= m)
    			ne[i][0] = j;
    	}
    	gn = log2(m);
    	for (j = 1; j <= gn; j++)
    		for (i = 1; i <= m; i++)
    			ne[i][j] = ne[ne[i][j - 1]][j - 1];
    	printf("%d
    ", calc(-2e9, 2e9));
    	S.insert((dd){-2e9, -2e9});
    	S.insert((dd){2e9, 2e9});
    	for (i = 1; i <= n; i++)
    	{
    		set<dd>::iterator x = S.lower_bound(a[i]), y;
    		--(y = x);
    		L = y -> y;
    		r = a[i].x;
    		l = a[i].y;
    		R = x -> x;
    		if (L >= r || l >= R)
    			continue;
    		if (!(calc(L + 1, R - 1) ^ (calc(L + 1, r - 1) + calc(l + 1, R - 1) + 1)))
    		{
    			printf("%d ", i);
    			S.insert(a[i]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    mysql查询缓存
    Mysql 通过binlog日志恢复数据
    mysqlbinlog命令详解
    修改vsftpd默认端口21
    centos 卸载vsftpd方法
    linux挂载u盘和卸载
    Linux下搭建FTP服务器
    fastjson SerializerFeature详解
    Spring JPA使用CriteriaBuilder动态构造查询
    jdk之jps的用法
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9794672.html
Copyright © 2011-2022 走看看