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<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,m;
struct node
{
int l,r;
int t1,t2;
int lt1,lt2;
int rt1,rt2;
}tree[maxn<<2];
void pushup(int cur)
{
tree[cur].t1=max(tree[cur*2].t1,tree[cur*2+1].t1);
tree[cur].t1=max(tree[cur].t1,tree[cur*2].rt1+tree[cur*2+1].lt1);
tree[cur].t2=max(tree[cur*2].t2,tree[cur*2+1].t2);
tree[cur].t2=max(tree[cur].t2,tree[cur*2].rt2+tree[cur*2+1].lt2);
tree[cur].lt1=tree[cur*2].lt1;
if(tree[cur].lt1==tree[cur*2].r-tree[cur*2].l+1)
tree[cur].lt1+=tree[cur*2+1].lt1;
tree[cur].lt2=tree[cur*2].lt2;
if(tree[cur].lt2==tree[cur*2].r-tree[cur*2].l+1)
tree[cur].lt2+=tree[cur*2+1].lt2;
tree[cur].rt1=tree[cur*2+1].rt1;
if(tree[cur].rt1==tree[cur*2+1].r-tree[cur*2+1].l+1)
tree[cur].rt1+=tree[cur*2].rt1;
tree[cur].rt2=tree[cur*2+1].rt2;
if(tree[cur].rt2==tree[cur*2+1].r-tree[cur*2+1].l+1)
tree[cur].rt2+=tree[cur*2].rt2;
}
void pushdown(int cur)
{
if(tree[cur].t1==tree[cur].r-tree[cur].l+1)
{
tree[cur*2].lt1=tree[cur*2].rt1=tree[cur*2].t1=tree[cur*2].r-tree[cur*2].l+1;
tree[cur*2+1].lt1=tree[cur*2+1].rt1=tree[cur*2+1].t1=tree[cur*2+1].r-tree[cur*2+1].l+1;
}
if(tree[cur].t1==0)
{
tree[cur*2].lt1=tree[cur*2].rt1=tree[cur*2].t1=0;
tree[cur*2+1].lt1=tree[cur*2+1].rt1=tree[cur*2+1].t1=0;
}
if(tree[cur].t2==tree[cur].r-tree[cur].l+1)
{
tree[cur*2].lt2=tree[cur*2].rt2=tree[cur*2].t2=tree[cur*2].r-tree[cur*2].l+1;
tree[cur*2+1].lt2=tree[cur*2+1].rt2=tree[cur*2+1].t2=tree[cur*2+1].r-tree[cur*2+1].l+1;
}
if(tree[cur].t2==0)
{
tree[cur*2].lt2=tree[cur*2].rt2=tree[cur*2].t2=0;
tree[cur*2+1].lt2=tree[cur*2+1].rt2=tree[cur*2+1].t2=0;
}
}
void build(int l,int r,int cur)
{
tree[cur].l=l;
tree[cur].r=r;
if(l==r)
{
tree[cur].t1=1;
tree[cur].t2=1;
tree[cur].lt1=tree[cur].lt2=1;
tree[cur].rt1=tree[cur].rt2=1;
return;
}
int mid=(r+l)>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
pushup(cur);
}
int query(int x,int cur)
{
if(tree[cur].l==tree[cur].r)
{
return tree[cur].l;
}
pushdown(cur);
if(tree[cur*2].t1>=x) return query(x,cur*2);
else if(tree[cur*2].rt1+tree[cur*2+1].lt1>=x) return tree[cur*2].r-tree[cur*2].rt1+1;
else return query(x,cur*2+1);
}
void update(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].lt1=0;
tree[cur].rt1=0;
tree[cur].t1=0;
return;
}
pushdown(cur);
if(pl<=tree[cur*2].r) update(pl,pr,cur<<1);
if(pr>=tree[cur*2+1].l) update(pl,pr,cur<<1|1);
pushup(cur);
}
int query2(int x,int cur)
{
if(tree[cur].l==tree[cur].r)
{
return tree[cur].l;
}
pushdown(cur);
if(tree[cur*2].t2>=x) return query2(x,cur*2);
else if(tree[cur*2].rt2+tree[cur*2+1].lt2>=x) return tree[cur*2].r-tree[cur*2].rt2+1;
else return query2(x,cur*2+1);
}
void update2(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].lt2=0;
tree[cur].rt2=0;
tree[cur].t2=0;
tree[cur].lt1=0;
tree[cur].rt1=0;
tree[cur].t1=0;
return;
}
pushdown(cur);
if(pl<=tree[cur*2].r) update2(pl,pr,cur<<1);
if(pr>=tree[cur*2+1].l) update2(pl,pr,cur<<1|1);
pushup(cur);
}
void update3(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].rt2=tree[cur].t2=tree[cur].lt2=tree[cur].r-tree[cur].l+1;
tree[cur].lt1=tree[cur].rt1=tree[cur].t1=tree[cur].r-tree[cur].l+1;
return;
}
pushdown(cur);
if(pl<=tree[cur*2].r) update3(pl,pr,cur<<1);
if(pr>=tree[cur*2+1].l) update3(pl,pr,cur<<1|1);
pushup(cur);
}
int main()
{
int t;
int nn=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
build(1,n,1);
char op[10];
int x,l,r;
printf("Case %d:\n",nn++);
while(m--)
{
scanf("%s",op);
if(op[0]=='D')
{
scanf("%d",&x);
if(tree[1].t1<x) printf("fly with yourself\n");
else
{
int ans=query(x,1);
printf("%d,let's fly\n",ans);
update(ans,ans+x-1,1);
}
}
else if(op[0]=='N')
{
scanf("%d",&x);
if(tree[1].t1>=x)
{
int ans=query(x,1);
printf("%d,don't put my gezi\n",ans);
update2(ans,ans+x-1,1);
}
else if(tree[1].t2>=x)
{
int ans=query2(x,1);
printf("%d,don't put my gezi\n",ans);
update2(ans,ans+x-1,1);
}
else
printf("wait for me\n");
}
else
{
scanf("%d%d",&l,&r);
update3(l,r,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
return 0;
}