hdu 4453 约会安排(线段树区间合并)
约会安排
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 433 Accepted Submission(s): 145
Problem Description
寒假来了,又到了小明和女神们约会的季节。
小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会。与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事。
我们已知小明一共有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!!”,不过小明一般都是三分钟热度,再有人来预定的话,小明就会按耐不住寂寞把学习新知识的时间分配出去。
小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会。与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事。
我们已知小明一共有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
每组数据以两个整数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!!”
输出样本(可复制此处):
“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
找最左边连续大于x的空间的位置。。
对于一个区间:
符合条件的这个位置要么在最左, 最右, 要么跨越该区间中点 。
否则就递归到左右子区间,并且符合上面的条件。
开一个LL[rt] , RR[rt] 表示区间最左边有多少个空位,最右边有多少连续空位。
就可以维护出来 。
对于题目要开两颗线段树, 一棵是DS+NS的, 一颗是NS的 。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstring> #include <map> #include <queue> using namespace std; typedef pair<int,int> pii ; #define X first #define Y second #define root 1,n,1 #define lr rt<<1 #define rr rt<<1|1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int N = 200010; const int mod = 10007; int n , m ; int lazy[N<<2][2] , LL[N<<2][2] , RR[N<<2][2] , ms[N<<2][2]; int s , x , y ; void build( int l , int r , int rt ) { for( int i = 0 ; i < 2 ; ++i ){ ms[rt][i] = LL[rt][i] = RR[rt][i] = r-l+1; // rest from left and right lazy[rt][i] = 0 ; // the state of pushdown } if( l == r ) return ; int mid = (l+r)>>1; build(lson),build(rson); } void Up( int l , int r , int rt , int i ) { int mid = (l+r)>>1; ms[rt][i] = max( max( ms[lr][i] , ms[rr][i] ) , RR[lr][i] + LL[rr][i] ) ; LL[rt][i] = LL[lr][i] ; if( LL[lr][i] == mid - l + 1 ) LL[rt][i] += LL[rr][i]; RR[rt][i] = RR[rr][i]; if( RR[rr][i] == r - mid ) RR[rt][i] += RR[lr][i]; } void Down( int l , int r , int rt , int i ) { if( l == r ) return ; int mid = (l+r)>>1 ; if( lazy[rt][i] == 1 ) { lazy[lr][i] = lazy[rr][i] = 1 ; ms[lr][i] = ms[rr][i] = 0 ; LL[lr][i] = RR[lr][i] = 0 ; LL[rr][i] = RR[rr][i] = 0 ; } if( lazy[rt][i] == -1 ) { lazy[lr][i] = lazy[rr][i] = -1 ; ms[lr][i] = mid - l + 1 ; ms[rr][i] = r - mid ; LL[lr][i] = RR[lr][i] = mid - l + 1 ; LL[rr][i] = RR[rr][i] = r - mid ; } lazy[rt][i] = 0 ; } void relax( int& a , int b ) { if( a == -1 ) a = b ; else a=(a<b?a:b); } void query( int l , int r , int rt , int x , int i ) { if( ms[rt][i] < x ) return ; int mid = (l+r)>>1; if( l == r ) { if( LL[rt][i] == 1 && x == 1 ) relax(s,l) ; return ; } else { Down(l,r,rt,i); if( LL[rt][i] >= x ) relax(s,l) ; if( RR[lr][i] + LL[rr][i] >= x ) relax( s , mid - RR[lr][i] + 1 ); if( RR[rt][i] >= x ) relax(s,r-RR[rt][i]+1); } query(lson,x,i) , query(rson,x,i); Up(l,r,rt,i); } void update( int l , int r , int rt , int L , int R , int i ) { if( l == L && r == R ) { ms[rt][i] = LL[rt][i] = RR[rt][i] = 0 ; lazy[rt][i] = 1 ; return ; } Down( l , r , rt ,i ) ; int mid = (l+r)>>1; if( R <= mid ) update(lson,L,R,i); else if( L > mid ) update(rson,L,R,i); else update(lson,L,mid,i) , update(rson,mid+1,R,i); Up(l,r,rt,i); } void clean( int l , int r , int rt , int L , int R ) { if( l == L && r == R ) { for( int i = 0 ; i < 2 ; ++i ) { LL[rt][i] = RR[rt][i] = ms[rt][i] = r - l + 1 ; lazy[rt][i] = -1 ; } return ; } Down(l,r,rt,0); Down(l,r,rt,1); int mid = (l+r)>>1; if( R <= mid ) clean(lson,L,R); else if( L > mid ) clean(rson,L,R); else clean(lson,L,mid) , clean(rson,mid+1,R); Up(l,r,rt,0); Up(l,r,rt,1); } int main() { #ifdef LOCAL freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif // LOCAL int _ , cas = 1 ; char op[11]; scanf("%d",&_); while( _-- ) { printf("Case %d:\n",cas++); scanf("%d%d",&n,&m); build(root); while( m-- ) { scanf("%s",op); s = -1 ; if( op[0] == 'D' ) { scanf("%d",&x); query(root,x,0); if( s == -1 ) puts("fly with yourself"); else { printf("%d,let's fly\n",s); update(root,s,s+x-1,0); } } else if( op[0] == 'N' ) { scanf("%d",&x); query( root , x , 0 ); if( s == -1 ) { query( root , x , 1 ); if( s == -1 ) puts("wait for me"); else { printf("%d,don't put my gezi\n",s); update(root,s,s+x-1,1); update(root,s,s+x-1,0); } } else { printf("%d,don't put my gezi\n",s); update(root,s,s+x-1,1); update(root,s,s+x-1,0); } } else { scanf("%d%d",&x,&y); puts("I am the hope of chinese chengxuyuan!!"); clean( root , x , y ); } } } }
only strive for your goal , can you make your dream come true ?