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

解题分析:由于本题要查询连续区间,所以要用到区间合并,每个点维护三个值,该点对应区间的最长连续长度,最长连续前、后缀长度。并且,本题还涉及一个优先级的概念,因此,建立两个线段树,对这两个线段树进行操作,从而达到模拟优先级的作用,具体实现见代码。
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5
  6 #define Lson rt<<1,l,mid
  7 #define Rson rt<<1|1,mid+1,r
  8 const int M =1e5+5;
  9 int n,q;
 10 int tr[M<<2][2],llen[M<<2][2],rlen[M<<2][2];
 11 int lazy[M<<2][2];
 12
 13 void Pushup(int rt,int len,int ty){   //区间合并,维护最长连续区间
 14     llen[rt][ty]=llen[rt<<1][ty];
 15     rlen[rt][ty]=rlen[rt<<1|1][ty];
 16     if(llen[rt<<1][ty]==(len-(len>>1)))llen[rt][ty]+=llen[rt<<1|1][ty];
 17     if(rlen[rt<<1|1][ty]==(len>>1))rlen[rt][ty]+=rlen[rt<<1][ty];
 18     tr[rt][ty]=max(max(tr[rt<<1][ty],tr[rt<<1|1][ty]),rlen[rt<<1][ty]+llen[rt<<1|1][ty]);
 19 }
 20 void Pushdown(int rt,int len,int ty){    //将lazy标记下放
 21     if(lazy[rt][ty]!=-1){
 22         int tmp=lazy[rt][ty];
 23         tr[rt<<1][ty]=llen[rt<<1][ty]=rlen[rt<<1][ty]=(len-(len>>1))*tmp;
 24         tr[rt<<1|1][ty]=llen[rt<<1|1][ty]=rlen[rt<<1|1][ty]=(len>>1)*tmp;
 25         lazy[rt<<1][ty]=lazy[rt<<1|1][ty]=tmp;
 26         lazy[rt][ty]=-1;
 27     }
 28 }
 29 void build(int rt,int l,int r,int ty){
 30     lazy[rt][ty]=-1;
 31     if(l==r){
 32         tr[rt][ty]=llen[rt][ty]=rlen[rt][ty]=1;   //值为1代表该点有时间,为0代表没时间
 33         return;
 34     }
 35     int mid=(l+r)>>1;
 36     build(Lson,ty);
 37     build(Rson,ty);
 38     Pushup(rt,r-l+1,ty);
 39 }
 40 void update(int rt,int l,int r,int L,int R,int c,int ty){
 41     if(L<=l&&r<=R){
 42         lazy[rt][ty]=c;
 43         tr[rt][ty]=llen[rt][ty]=rlen[rt][ty]=(r-l+1)*c;
 44         return;
 45     }
 46     Pushdown(rt,r-l+1,ty);
 47     int mid=(l+r)>>1;
 48     if(L<=mid)update(Lson,L,R,c,ty);
 49     if(R>mid)update(Rson,L,R,c,ty);
 50     Pushup(rt,r-l+1,ty);
 51 }
 52 int query(int rt,int l,int r,int len,int ty){   //返回满足连续区间>=len的区间最左值
 53     if(l==r)return l;
 54     Pushdown(rt,r-l+1,ty);
 55     int mid=(l+r)>>1;
 56     //因为要尽量使符合要求的区间靠前,所以这里按左、中、右的顺序来查询
 57     if(tr[rt<<1][ty]>=len)return query(Lson,len,ty);
 58     else if(rlen[rt<<1][ty]+llen[rt<<1|1][ty]>=len)return mid-rlen[rt<<1][ty]+1;   //如果是在左右子区间的后缀、前缀之间,则直接返回左区间的后缀最左值的下标
 59     else return query(Rson,len,ty);
 60 }
 61 int main(){
 62     int T,ncase=0;scanf("%d",&T);
 63     while(T--){
 64         scanf("%d%d",&n,&q);
 65         build(1,1,n,0);  //基友的请求建一个线段树
 66         build(1,1,n,1);  //女神的请求建一颗线段树,更新的时候,根据优先级,对这两个不同的线段树进行操作
 67         char op[10];
 68         int x,y;
 69         printf("Case %d:\n", ++ncase);
 70         while(q--){
 71             scanf("%s",op);
 72             if(op[0]==‘D‘){
 73                 scanf("%d",&x);
 74                 if(tr[1][0]>=x){   //如果存在>=x的连续区间
 75                     int ans=query(1,1,n,x,0);   //得到符合要求区间的最左值下标
 76                     printf("%d,let‘s fly\n", ans);
 77                     update(1,1,n,ans,ans+x-1,0,0);   //只更新基友树上的时间安排
 78                 }
 79                 else printf("fly with yourself\n");
 80             }
 81             else if(op[0]==‘N‘){
 82                 scanf("%d",&x);
 83                 if(tr[1][0]>=x){   //如果不用占用基友的时间也能与女神约会,即如果优先级低的基友树上也能满足
 84                     int ans=query(1,1,n,x,0);
 85                     printf("%d,don‘t put my gezi\n", ans);
 86                     update(1,1,n,ans,ans+x-1,0,0);  //基友树上要更新一段
 87                     update(1,1,n,ans,ans+x-1,0,1);  //女神树上也要更新同样一段,因为女神的要求之间优先级是相同的,如果有女神占了一段时间,那么其它女神也不能占用
 88                 }
 89                 else{
 90                     if(tr[1][1]>=x){   //只要女神树上能满足,此时即使基友树上发生冲突也不管,如果需要占用基友时间,直接强制更新,体现了女神的高优先级
 91                         int ans=query(1,1,n,x,1);
 92                         printf("%d,don‘t put my gezi\n", ans);
 93                         update(1,1,n,ans,ans+x-1,0,0);
 94                         update(1,1,n,ans,ans+x-1,0,1);
 95                     }
 96                     else printf("wait for me\n");
 97                 }
 98             }
 99             else{
100                 scanf("%d%d", &x, &y);
101                 printf("I am the hope of chinese chengxuyuan!!\n");
102                 update(1,1,n,x,y,1,0);    //同时将基友树和女神树上的要求全部清除
103                 update(1,1,n,x,y,1,1);
104             }
105         }
106     }
107     return 0;
108 }


2018-10-01

原文地址:https://www.cnblogs.com/00isok/p/9735550.html

时间: 2024-10-07 12:01:25

HDU 4553 约会安排 (区间合并)【线段树】的相关文章

HDU 4553 约会安排(二维线段树)

Problem Description 寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复"呵呵",所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事. 我们已知小明一共有T的空闲时间,期间会有很多女神或者基友来找小明. 作为一个操作系统曾经怒考71分的大神,小明想到了一个算法,即"首次适应算法",根据操作系统课本的描述,就是找一段最

hdu 4553 约会安排 (两个线段树维护区间)

include include include include include include include include define ll long long define FOR(i,l,r) for(int i = l ; i <= r ;++i ) define inf 1<<30 define EPS (1e-9) define lson(p) (p<<1) define rson(p) (p<<1|1) using namespace std;

【区间合并线段树】BZOJ1593-安排住宿

[题目大意] 查询最左端的连续长度区间:或批量修改一些区间.[思路] 区间合并线段树……复习一下.POJ上有一样的题目,我居然还借用了别人的权限号去做BZOJ,简直愚昧到没朋友[笑cry] 处理方法以前的博文里有,这里有不赘述了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstdlib> 6 using

约会安排---hdu4553(线段树,麻烦的区间覆盖)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 算是poj3667的加强版,建立两颗线段树,一个是DS区间,另一个是NS区间.那么根据题意,如果是DS的请求,那么首先查找DS的区间,如果有满足的区间就更新DS区间,NS的区间不需要更新.如果是NS的请求,首先看DS区间是否有满足的区间,否则查找NS区间,如果有就同时更新DS区间和NS区间.那么可以归纳为,只要是NS的请求,就同时更新两颗线段树,否则只更新DS的线段树. 注意输出要从Outpu

【区间合并线段树】HDU 4509 模板

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int MAXN=100000+50; const int rt=0; vector<

hdu 4553 约会安排

约会安排 http://acm.hdu.edu.cn/showproblem.php?pid=4553 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description 寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会.与此同时,也有很多基友找他开黑

BZOJ 2243:染色(树链剖分+区间合并线段树)

[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”.请你写一个程序依次完成这m个操作.Input第一行包含2个整数n和m,分别表示节点数和操作数:第二行包含n个正整数表示n个节点的初始颜色下面 行每行包含两个整数x和y,表示x和y之间有一条无向边.下面 行每行描述一个操作:“C

【线段树】HDU 3397 Sequence operation 区间合并

操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters into '1's in [a , b] 2 a b change all '0's into '1's and change all '1's into '0's in [a, b] Output operations: 3 a b output the number of '1's in [a,

hdu 4893 Wow! Such Sequence!(线段树功能:单点更新,区间更新相邻较小斐波那契数)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 --------------------------------------------------------------------------------------------------------------------------------------------