约会安排 - HDU 4553 - 线段树 - 区间合并
2017-06-04 11:09
357 查看
约会安排 - HDU 4553 - 线段树 - 区间合并
思路
国际惯例中文题目直接说思路,DS QT:找一段最靠前长度为QT的空间;
NS QT:找一段最靠前长度为QT的空间,如果没有找到可以将DS占据的空间当做空闲空间,找一段最靠前的空间;
STUDY!! L R:清空
[L,R]区间的空间。
用两个线段树,一个记录DS,一个记录NS,维护最大左区间ma_l,最大右区间ma_r,以及区间内最大区间ma。
判断是否可以容下一端长为qt的空间可以直接通过比较根节点的ma和qt的大小就可以。因为ma记录的是当前区间的最大空闲区间,也就是说只需要比较
qt和
tree[1].ma大小即可判断空间是否足够。
代码
// // main.cpp // L // // Created by LucienShui on 2017/6/4. // Copyright © 2017年 LucienShui. All rights reserved. // #include <iostream> #include <algorithm> #include <set> #include <string> #include <vector> #include <queue> #include <map> #include <stack> #include <iomanip> #include <cstdio> #include <cstring> #include <cmath> #include <cctype> #define memset(a,b,n) memset(a,b,n*sizeof(a[0])) #define il inline #define ll long long #define ull unsigned long long using namespace std; #define ls (u<<1) #define rs (u<<1|1) #define lson u<<1,l,mid #define rson u<<1|1,mid+1,r #define maxn 100007 struct node { int l , r ; int ma_l ; int ma_r ; int ma ; int lazy ; }tree[2][maxn<<2] ; void build(int l , int r , int u) { for(int i = 0;i < 2;i++) { tree[i][u].l = l ; tree[i][u].r = r; tree[i][u].lazy = -1; tree[i][u].ma_l = tree[i][u].ma = tree[i][u].ma_r = (r - l + 1) ; } if(l == r)return ; int mid = (l + r)>>1 ; build(l , mid , ls) ; build(mid+1 , r , rs) ; } void push_down(int u) { for(int i = 0 ;i < 2;i++) if(tree[i][u].lazy != -1) { tree[i][ls].ma_l = tree[i][ls].ma_r = tree[i][ls].ma = (tree[i][ls].r - tree[i][ls].l + 1)*tree[i][u].lazy ; tree[i][rs].ma_l = tree[i][rs].ma_r = tree[i][rs].ma = (tree[i][rs].r - tree[i][rs].l + 1)*tree[i][u].lazy ; tree[i][ls].lazy = tree[i][rs].lazy = tree[i][u].lazy ; tree[i][u].lazy = -1; } } void push_up(int u) { for(int i = 0 ;i < 2;i++) { tree[i][u].ma_l = tree[i][ls].ma_l ; tree[i][u].ma_r = tree[i][rs].ma_r ; tree[i][u].ma = max(max(tree[i][ls].ma ,tree[i][rs].ma) ,tree[i][ls].ma_r+tree[i][rs].ma_l) ; if(tree[i][u].ma_l == (tree[i][ls].r - tree[i][ls].l + 1)) tree[i][u].ma_l += tree[i][rs].ma_l ; if(tree[i][u].ma_r == (tree[i][rs].r - tree[i][rs].l + 1)) tree[i][u].ma_r += tree[i][ls].ma_r ; } } int query(int u , const int flag , const int qt) { if(tree[flag][u].l == tree[flag][u].r)//如果到达叶节点 return tree[flag][u].l ;//返回叶节点的坐标 push_down(u) ; if(tree[flag][ls].ma >= qt)//优先向前安排,所以优先询问左子树是否可以容纳下qt return query(ls , flag ,qt) ; else if(tree[flag][ls].ma_r + tree[flag][rs].ma_l >= qt) //询问中间,左子树的右区间加上右子树的左区间是否可以容纳下qt return tree[flag][ls].r - tree[flag][ls].ma_r + 1 ; //如果可以容纳下,那么左子树的右区间的左端点就一定是可以容纳下qt的第一个区间的左端点 else return query(rs , flag , qt) ;//最坏的情况下判断右子树是否可以容纳下qt } void update(int a , int b , int u , const int flag , const int tag) { if(tree[flag][u].l >= a && tree[flag][u].r <= b) { tree[flag][u].lazy = tag; tree[flag][u].ma_l = tree[flag][u].ma = tree[flag][u].ma_r = (tree[flag][u].r - tree[flag][u].l + 1)*tag ; return ; } push_down(u) ; int mid = (tree[flag][u].l + tree[flag][u].r) >> 1 ; if(a <= mid)update(a , b , ls , flag , tag) ; if(b > mid)update(a , b , rs , flag , tag) ; push_up(u) ; } int main () { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE int T ; scanf("%d" , &T) ; int cas = 0 ; while(T--) { int N , Q ; scanf("%d%d" ,&N , &Q) ; build(1 , N , 1) ; char ch[10] ; int L , R , qt ; printf("Case %d:\n" , ++cas) ; while(Q--) { scanf("%s" , ch) ; if(ch[0] == 'D') { scanf("%d" , &qt) ; if(tree[1][1].ma < qt) { puts("fly with yourself"); continue ; } int pos = query(1 , 1 , qt) ; update(pos , pos + qt - 1 , 1 , 1 , 0) ; printf("%d,let's fly\n" , pos) ; } else if(ch[0] == 'N') { scanf("%d" , &qt) ; int pos ; if(tree[1][1].ma < qt && tree[0][1].ma < qt) { puts("wait for me"); continue ; } else if(tree[1][1].ma >= qt) pos = query(1 , 1 , qt) ; else pos = query(1 , 0 , qt) ; printf("%d,don't put my gezi\n" , pos) ; update(pos , pos + qt - 1, 1, 0, 0) ; update(pos , pos + qt - 1, 1, 1, 0) ; } else if(ch[0] == 'S') { scanf("%d%d" , &L , &R) ; update(L , R , 1 , 0 , 1) ; update(L , R , 1 , 1 , 1) ; puts("I am the hope of chinese chengxuyuan!!") ; } } } return 0 ; }
相关文章推荐
- HDU 4553 约会安排(线段树区间合并&优先级)
- HDU - 4553 约会安排 (线段树区间合并)
- HDU - 4553 约会安排(线段树 区间合并)
- HDU 4553 约会安排(线段树区间合并)
- HDU 4553 约会安排 (线段树 -- 区间合并(多种优先级的区间合并) )
- HDU 4553 约会安排 (线段树,区间合并)
- Poj 3667 Hotel + Hdu 4553 约会安排 (线段树最左空区间)
- hdu 4453 约会安排(线段树区间合并)
- HDU-4553 约会安排 线段树区间更新
- hdoj 4553 约会安排 【线段树区间合并】
- HDU-4553-约会安排(线段树维护最长连续区间)
- HDU 4553:约会安排(区间合并)
- HDU 4553 约会安排 [线段树]
- HDU--杭电--4553--约会安排--线段树
- HDU 4553 线段树双关键字区间合并
- HDU - 4553 线段树区间合并
- HDU4553:约会安排(线段树)(第三部分 区间合并)
- HDU 4553 约会安排 [线段树]
- HDU 4553 约会安排(二维线段树)
- HDU4553:约会安排(线段树区间合并)