当前位置: 首页 > news >正文

[BZOJ1178][Apio2009]CONVENTION会议中心

[BZOJ1178][Apio2009]CONVENTION会议中心

试题描述

Siruseri政府建造了一座新的会议中心。许多公司对租借会议中心的会堂很感兴趣,他们希望能够在里面举行会议。 对于一个客户而言,仅当在开会时能够独自占用整个会堂,他才会租借会堂。会议中心的销售主管认为:最好的策略应该是将会堂租借给尽可能多的客户。显然,有可能存在不止一种满足要求的策略。 例如下面的例子。总共有4个公司。他们对租借会堂发出了请求,并提出了他们所需占用会堂的起止日期(如下表所示)。 开始日期 结束日期 公司1 4 9 公司2 9 11 公司3 13 19 公司4 10 17 上例中,最多将会堂租借给两家公司。租借策略分别是租给公司1和公司3,或是公司2和公司3,也可以是公司1和公司4。注意会议中心一天最多租借给一个公司,所以公司1和公司2不能同时租借会议中心,因为他们在第九天重合了。 销售主管为了公平起见,决定按照如下的程序来确定选择何种租借策略:首先,将租借给客户数量最多的策略作为候选,将所有的公司按照他们发出请求的顺序编号。对于候选策略,将策略中的每家公司的编号按升序排列。最后,选出其中字典序最小1的候选策略作为最终的策略。 例中,会堂最终将被租借给公司1和公司3:3个候选策略是{(1,3),(2,3),(1,4)}。而在字典序中(1,3)<(1,4)<(2,3)。 你的任务是帮助销售主管确定应该将会堂租借给哪些公司。

输入

输入的第一行有一个整数N,表示发出租借会堂申请的公司的个数。第2到第N+1行每行有2个整数。第i+1行的整数表示第i家公司申请租借的起始和终止日期。对于每个公司的申请,起始日期为不小于1的整数,终止日期为不大于10^9的整数。

输出

输出的第一行应有一个整数M,表示最多可以租借给多少家公司。第二行应列出M个数,表示最终将会堂租借给哪些公司。

输入示例

4
4 9
9 11
13 19
10 17

输出示例

2
1 3 

数据规模及约定

对于50%的输入,N≤3000。在所有输入中,N≤200000 请注意使用Readln读入数据........

题解

这里把所有的“公司”等价成左端点为“开始日期”,右端点为“结束日期”的线段。

如果只考虑第一问,贪心即可,按右端点升序排序,把所有包含别的线段的线段去掉数个数即可。

加了个字典序,就好玩了。

然而“字典序”还是要用到贪心,于是从1~n条线段依次判断,若第 i 条线段满足加进去后不影响最终能选的线段条数则毫无疑问地选择 i。如何判断是核心问题,我们可以用倍增算法:令 f(j, i) 表示从点 i 开始,选择 2j 个不相交线段可能的最靠左的点,那么就不难算出一个区间 [L, R] 中最优能选择的线段条数了(详见代码中的 getans() 函数)。以后判断线段时,先确保当前线段与前面所有加进来的线段无交集,再找到这个线段的前驱 ql 和后继 qr,然后当 ans(ql + 1, qr - 1) = ans(ql + 1, l - 1) + 1 + ans(r + 1, qr - 1) 时说明这个线段可以选进来(ans(i, j)表示区间[i, j]中最优能够选择的线段的条数,l、r 表示当前线段左、右端点)。

至于判断线段是否有交集,可以用个平衡树找前驱后继。(如果不怕慢可以用set)

代码注释多,请忽略。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;

const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
    if(Head == tail) {
        int l = fread(buffer, 1, BufferSize, stdin);
        tail = (Head = buffer) + l;
    }
    return *Head++;
}
int read() {
    int x = 0, f = 1; char c = Getchar();
    while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    return x * f;
}

#define maxn 200010
#define maxm 400010
#define maxlog 20
#define oo 2147483647
int n, N, cnt, num[maxm], c, ans[maxn];
struct Line { int l, r, id; } ls[maxn];

int Right[maxlog][maxm];
void init() {
	for(int j = 1; j < maxlog; j++)
		for(int i = 1; i <= N && Right[j-1][i] < N && Right[j-1][Right[j-1][i]+1] <= N; i++)
			Right[j][i] = Right[j-1][Right[j-1][i]+1];
	return ;
}
int getans(int l, int r) {
	if(l > r) return 0;
	int ans = 0, p = l;
	for(int i = maxlog-1; i >= 0; i--) if(Right[i][p] <= r)
		ans += (1 << i), p = Right[i][p];
	return ans;
}

int ToT, fa[maxm], ch[maxm][2], root;
struct Node { int v, r, minv, maxv, siz; } nodes[maxm];
void newnode(int& o, int v) {
	nodes[o = ++ToT] = (Node) { v, rand(), v, v, 1 };
	return ;
}
void maintain(int o) {
	Node &u = nodes[o], &lc = nodes[ch[o][0]], &rc = nodes[ch[o][1]];
	u.minv = min(min(lc.minv, rc.minv), u.v);
	u.maxv = max(max(lc.maxv, rc.maxv), u.v);
	u.siz = lc.siz + 1 + rc.siz;
	return ;
}
void rotate(int u) {
	int y = fa[u], z = fa[y], l = 0, r = 1;
	if(ch[y][1] == u) swap(l, r);
	if(z >= 0) ch[z][ch[z][1]==y] = u;
	else root = u;
	fa[u] = z; fa[y] = u; fa[ch[u][r]] = y;
	ch[y][l] = ch[u][r]; ch[u][r] = y;
	maintain(y); maintain(u);
	return ;
}
void insert(int& o, int v, int pa) {
	if(!o) {
		newnode(o, v);
		fa[o] = pa;
		return ;
	}
	int d = v > nodes[o].v;
	insert(ch[o][d], v, o);
	if(nodes[ch[o][d]].r > nodes[o].r) rotate(ch[o][d]);
	maintain(o);
	return ;
}
int _l, _r, _s;
void findp(int o, int v) {
//	printf("\no: %d %d %d %d\n", o, nodes[o].v, ch[o][0], nodes[ch[o][0]].maxv);
	if(!o) { _l = _r = -1; return ; }
	if(nodes[o].v == v){ _l = _r = v; return ; }
	if(nodes[o].v > v && ch[o][0] && nodes[ch[o][0]].maxv < v) {
		_s += nodes[ch[o][0]].siz;
		_l = nodes[ch[o][0]].maxv; _r = nodes[o].v;
		return ;
	}
	if(nodes[o].v < v && ch[o][1] && nodes[ch[o][1]].minv > v) {
		_s += nodes[ch[o][0]].siz + 1;
		_l = nodes[o].v; _r = nodes[ch[o][1]].minv;
		return ;
	}
	int d = v > nodes[o].v;
	if(d) _s += nodes[ch[o][0]].siz + 1;
	findp(ch[o][d], v);
	return ;
}

int main() {
//	freopen("data.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	srand(1314);
	n = read(); N = n << 1;
	for(int i = 1; i <= n; i++) {
		num[++cnt] = ls[i].l = read(); num[++cnt] = ls[i].r = read();
		ls[i].id = i;
	}
	sort(num + 1, num + cnt + 1);
	unique(num + 1, num + cnt + 1);
	for(int i = 1; i <= n; i++) {
		ls[i].l = lower_bound(num + 1, num + cnt + 1, ls[i].l) - num;
		ls[i].r = lower_bound(num + 1, num + cnt + 1, ls[i].r) - num;
	}
	
	int p = 0;
	for(int j = 0; j < maxlog; j++)
		for(int i = 1; i <= N; i++) Right[j][i] = N + 1;
	for(int i = 1; i <= n; i++) Right[0][ls[i].l] = min(Right[0][ls[i].l], ls[i].r);
//	for(int i = 1; i <= n; i++) printf("%d %d\n", ls[i].l, ls[i].r);
	for(int i = N - 1; i; i--) Right[0][i] = min(Right[0][i], Right[0][i+1]);
//	for(int i = 1; i <= N; i++) printf("%d ", Right[0][i]); putchar('\n');
	init();
	printf("%d\n", getans(1, N));
	nodes[0] = (Node) { 0, 0, oo, -oo, 0 };
	insert(root, 0, -1); insert(root, N + 1, -1);
	for(int i = 1; i <= n; i++) {
		findp(root, ls[i].l); int ll = _l, lr = _r; _s = 0;
		findp(root, ls[i].r); int rl = _l, rr = _r;
//		printf("%d [%d, %d]: %d %d %d %d %d\n", i, ls[i].l, ls[i].r, ll, lr, rl, rr, _s);
		if(ll == lr || rl == rr || ll != rl || lr != rr || !(_s & 1)) continue;
		ll++; lr--;
		if(getans(ll, lr) == getans(ll, ls[i].l-1) + 1 + getans(ls[i].r+1, lr)) {
			ans[++c] = i; insert(root, ls[i].l, -1); insert(root, ls[i].r, -1);
		}
	}
//	printf("getans: %d %d\n", getans(1, 3), Right[0][1]);
	
	for(int i = 1; i <= c; i++) printf("%d ", ans[i]); putchar('\n');
//	printf("%d\n", c);
	
	return 0;
}
/*
5
4 8
3 6
1 4
1 3
9 10
*/

 

转载于:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5428338.html

相关文章:

  • 20145302张薇《Java程序设计》第八周学习总结
  • QT(6)Basic Layout学习
  • EventSource
  • UTC时间转换为标准时间
  • 软件工程(二)可行性分析
  • OOM-KILLer的演进与新的启发式策略
  • JMS学习(二)之ActiveMQ
  • 断点上有一个斜杠
  • 第九周
  • S3C2440-IIS放音
  • 记住密码超简单实现(C#)
  • CSS布局居中
  • Servlet和JSP关系浅析
  • selenium 获取某元素的 某属性 的值
  • BestCoder Round #81 (div.2) 1003 String
  • Android框架之Volley
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • Java精华积累:初学者都应该搞懂的问题
  • Redash本地开发环境搭建
  • Redis在Web项目中的应用与实践
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SpiderData 2019年2月13日 DApp数据排行榜
  • vue-router的history模式发布配置
  • 驱动程序原理
  • 深入 Nginx 之配置篇
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 用quicker-worker.js轻松跑一个大数据遍历
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​什么是bug?bug的源头在哪里?
  • #预处理和函数的对比以及条件编译
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (9)目标检测_SSD的原理
  • (C语言)逆序输出字符串
  • (Python第六天)文件处理
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (一)插入排序
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)socket Aio demo
  • .Family_物联网
  • .net 无限分类
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .Net 应用中使用dot trace进行性能诊断
  • .NET的微型Web框架 Nancy
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .net与java建立WebService再互相调用
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • @Autowired标签与 @Resource标签 的区别
  • [2013AAA]On a fractional nonlinear hyperbolic equation arising from relative theory
  • [Asp.net MVC]Asp.net MVC5系列——Razor语法