HDU 4553 约会安排 (区间合并)【线段树】
<题目链接>
小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会。与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事。
我们已知小明一共有T的空闲时间,期间会有很多女神或者基友来找小明。
作为一个操作系统曾经怒考71分的大神,小明想到了一个算法,即“首次适应算法”,根据操作系统课本的描述,就是找一段最靠前的符合要求的连续空间分配给每个请求,由此小明做出了一个决定:
当一个基友来找小明时,小明就根据“首次适应算法”来找一段空闲的时间来和基友约好,如果找到,就说“X,let’s fly”(此处,X为开始时间),否则就说“fly with yourself”;
当女神来找小明时,先使用一次“首次适应算法”,如果没有找到,小明就冒着木叽叽的风险无视所有屌丝基友的约定,再次使用“无视基友首次适应算法”,两次只要有一次找到,就说“X,don’t put my gezi”(此处,X为开始时间),否则就说“wait for me”
当然,我们知道小明不是一个节操负无穷的人,如果和女神约会完,还有剩余时间,他还是会和原来约好的基友去dota的。(举个例子:小西(屌丝)和小明约好在1~5这个时间单位段内打dota,这时候,女神来和小明预约长度为3的时间段,那么最终就是1~3小明去和女神约会,搞定后在4~5和小西打dota)
小明偶尔也会想要学习新知识,此时小明就会把某一个时间区间的所有已经预定的时间全部清空用来学习并且怒吼“I am the hope of chinese chengxuyuan!!”,不过小明一般都是三分钟热度,再有人来预定的话,小明就会按耐不住寂寞把学习新知识的时间分配出去。
Input
输入第一行为CASE,表示有CASE组测试数据;
每组数据以两个整数T,N开始,T代表总共的时间,N表示预约请求的个数;
接着的N行,每行表示一个女神或者基友的预约,“NS QT”代表一个女神来找小明约一段长为QT的时间,“DS QT”则代表一个屌丝的长为QT的请求,当然也有可能是小明想学知识了,“STUDY!! L R”代表清空L~R区间内的所有请求。
[Technical Specification]
1. 1 <= CASE <= 30
2. 1 <= T, N <= 100000
3. 1 <= QT <= 110000
4. 1 <= L <= R <=T
Output
对于每一个case,第一行先输出“Case C:”代表是第几个case,然后N行,每行对应一个请求的结果(参照描述)。
输出样本(可复制此处):
“X,let's fly”,”fly with yourself”,”X,don't put my gezi”,”wait for me”,”I am the hope of chinese chengxuyuan!!”
Sample Input
1
5 6
DS 3
NS 2
NS 4
STUDY!! 1 5
DS 4
NS 2
Sample Output
Case 1:
1,let's fly
4,don't put my gezi
wait for me
I am the hope of chinese chengxuyuan!!
1,let's fly
1,don't put my gezi
解题分析:
由于本题要查询连续区间,所以要用到区间合并,每个点维护三个值,该点对应区间的最长连续长度,最长连续前、后缀长度。并且,本题还涉及一个优先级的概念,因此,建立两个线段树,对这两个线段树进行操作,从而达到模拟优先级的作用,具体实现见代码。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define Lson rt<<1,l,mid
#define Rson rt<<1|1,mid+1,r
const int M =1e5+;
int n,q;
int tr[M<<][],llen[M<<][],rlen[M<<][];
int lazy[M<<][]; void Pushup(int rt,int len,int ty){ //区间合并,维护最长连续区间
llen[rt][ty]=llen[rt<<][ty];
rlen[rt][ty]=rlen[rt<<|][ty];
if(llen[rt<<][ty]==(len-(len>>)))llen[rt][ty]+=llen[rt<<|][ty];
if(rlen[rt<<|][ty]==(len>>))rlen[rt][ty]+=rlen[rt<<][ty];
tr[rt][ty]=max(max(tr[rt<<][ty],tr[rt<<|][ty]),rlen[rt<<][ty]+llen[rt<<|][ty]);
}
void Pushdown(int rt,int len,int ty){ //将lazy标记下放
if(lazy[rt][ty]!=-){
int tmp=lazy[rt][ty];
tr[rt<<][ty]=llen[rt<<][ty]=rlen[rt<<][ty]=(len-(len>>))*tmp;
tr[rt<<|][ty]=llen[rt<<|][ty]=rlen[rt<<|][ty]=(len>>)*tmp;
lazy[rt<<][ty]=lazy[rt<<|][ty]=tmp;
lazy[rt][ty]=-;
}
}
void build(int rt,int l,int r,int ty){
lazy[rt][ty]=-;
if(l==r){
tr[rt][ty]=llen[rt][ty]=rlen[rt][ty]=; //值为1代表该点有时间,为0代表没时间
return;
}
int mid=(l+r)>>;
build(Lson,ty);
build(Rson,ty);
Pushup(rt,r-l+,ty);
}
void update(int rt,int l,int r,int L,int R,int c,int ty){
if(L<=l&&r<=R){
lazy[rt][ty]=c;
tr[rt][ty]=llen[rt][ty]=rlen[rt][ty]=(r-l+)*c;
return;
}
Pushdown(rt,r-l+,ty);
int mid=(l+r)>>;
if(L<=mid)update(Lson,L,R,c,ty);
if(R>mid)update(Rson,L,R,c,ty);
Pushup(rt,r-l+,ty);
}
int query(int rt,int l,int r,int len,int ty){ //返回满足连续区间>=len的区间最左值,掌握这种query函数
if(l==r)return l;
Pushdown(rt,r-l+,ty);
int mid=(l+r)>>;
//因为要尽量使符合要求的区间靠前,所以这里按左、中、右的顺序来查询
if(tr[rt<<][ty]>=len)return query(Lson,len,ty);
else if(rlen[rt<<][ty]+llen[rt<<|][ty]>=len)return mid-rlen[rt<<][ty]+; //如果是在左右子区间的后缀、前缀之间,则直接返回左区间的后缀最左值的下标
else return query(Rson,len,ty);
}
int main(){
int T,ncase=;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&q);
build(,,n,); //基友的请求建一个线段树
build(,,n,); //女神的请求建一颗线段树,更新的时候,根据优先级,对这两个不同的线段树进行操作
char op[];
int x,y;
printf("Case %d:\n", ++ncase);
while(q--){
scanf("%s",op);
if(op[]=='D'){
scanf("%d",&x);
if(tr[][]>=x){ //如果存在>=x的连续区间
int ans=query(,,n,x,); //得到符合要求区间的最左值下标
printf("%d,let's fly\n", ans);
update(,,n,ans,ans+x-,,); //只更新基友树上的时间安排
}
else printf("fly with yourself\n");
}
else if(op[]=='N'){
scanf("%d",&x);
if(tr[][]>=x){ //如果不用占用基友的时间也能与女神约会,即如果优先级低的基友树上也能满足
int ans=query(,,n,x,);
printf("%d,don't put my gezi\n", ans);
update(,,n,ans,ans+x-,,); //基友树上要更新一段
update(,,n,ans,ans+x-,,); //女神树上也要更新同样一段,因为女神的要求之间优先级是相同的,如果有女神占了一段时间,那么其它女神也不能占用
}
else{
if(tr[][]>=x){ //只要女神树上能满足,此时即使基友树上发生冲突也不管,如果需要占用基友时间,直接强制更新,体现了女神的高优先级
int ans=query(,,n,x,);
printf("%d,don't put my gezi\n", ans);
update(,,n,ans,ans+x-,,);
update(,,n,ans,ans+x-,,);
}
else printf("wait for me\n");
}
}
else{
scanf("%d%d", &x, &y);
printf("I am the hope of chinese chengxuyuan!!\n");
update(,,n,x,y,,); //同时将基友树和女神树上的要求全部清除
update(,,n,x,y,,);
}
}
}
return ;
}
2018-10-01
HDU 4553 约会安排 (区间合并)【线段树】的更多相关文章
- HDU 4553 约会安排(线段树区间合并+双重标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 题目大意:就是有三种操作: ①DS x,安排一段长度为x的空闲时间跟屌丝一起,输出这段时间的起点 ...
- HDU - 4553 约会安排(区间合并)
https://cn.vjudge.net/problem/HDU-4553 Description 寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的 ...
- 约会安排---hdu4553(线段树,麻烦的区间覆盖)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 算是poj3667的加强版,建立两颗线段树,一个是DS区间,另一个是NS区间.那么根据题意, ...
- hdu 4553 约会安排
约会安排 http://acm.hdu.edu.cn/showproblem.php?pid=4553 Time Limit: 2000/1000 MS (Java/Others) Memory ...
- BZOJ 2243:染色(树链剖分+区间合并线段树)
[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...
- HDU 1540 区间合并线段树
题目大意: 就是给定一堆位置,进行删除还原,最后找到 t 位置上的最大连续位置 #include <cstdio> #include <cstring> #include &l ...
- HDU 5029 Relief grain(离线+线段树+启发式合并)(2014 ACM/ICPC Asia Regional Guangzhou Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5029 Problem Description The soil is cracking up beca ...
- hdu 5700区间交(线段树)
区间交 Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
随机推荐
- Oracle 数据库实例简介
回到顶部 一:Oracle 数据库实例简介 1:数据库实例的启动顺序: 使用数据库其实就是访问内存.即:数据库实例.数据库的启动是顺序是 先 nomount ----> mount --- ...
- Confluence 6 配置文件和key
找到配置文件 缓存的配置文件是存储在 <confluence-home>/shared-home/config/cache-settings-overrides.properties 中的 ...
- Linux 用户切换、修改用户名、修改密码
一.用户切换 "$":普通用户提示符 "#":root用户提示符 1.普通用户到root: 方式一:命令:su然后输入root密码 此种方式只是切换了root身 ...
- linux基础实操四
实操一: 1)为新加的硬盘分区,一个主分区大小为10剩余空间给扩展分区,在扩展分区上划分2个逻辑分别为5G 2)式化主分区为ext3系统 #mkfs.ext3 /dev/sdb1 3 将逻辑分区设置为 ...
- noip 2018游记
憋了好久的游记... 考虑到写游记是oi界的传统,所以还是应该写一篇的. day0: 上午9:30的火车出发,车上颓三国杀! 中午12:00到了大连,下午2:00才开始试机,还是得先去大连大学,在食堂 ...
- python字符编码和文件处理
一.了解字符编码的知识储备 1.文本编辑器存取文件的原理(nodepad++,python,word) 打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的内容也都是存放于内存中的,断 ...
- spring-data-mongo的MongoTemplate开发
spring-data-mongo的MongoTemplate开发 1.在实体类Customer.Java中引入注解表明转换方式 @Document //文档 public class Custo ...
- 使用sysbench 0.5 对mysql 进行性能、压力测试
sysbench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.目前sysbench代码托管在launchpad上,项目地址:https://launc ...
- office web apps搭建与解决方案
微软office在线预览解决方案https://view.officeapps.live.com/op/view.aspx?src=http://storage.xuetangx.com/public ...
- Project 2013 安装找不到office.zh cn的解决办法
先按照百度的办法,去“C:\Users\<你的电脑名>\AppData\Local\Temp\”下找类似“OWPFD24.tmp”的文件夹,结果发现并没有这个文件夹 , 没办法,自己硬着头 ...