http://acm.hdu.edu.cn/showproblem.php?pid=4553
题意:有个屌丝有T的空闲时间。每次有人与他约t的时间,他都会找到最靠前的一段符合要求的时间,称为“最先适应算法”。
1,如果基友约他,他就会按“最先适应算法”去找,找到就约否则不约。
2,如果女神约他,他也会先按原先的方法去找,如果找不到,那他会忽略所有与基友的约定而通过原来的方法去找跟女神约会的时间,找到就约否则不约。
3,有时他会脑抽,选择一个区间 [l,r] ,将该区间的安排都清空。
思路:
可以用两棵线段树去维护这段时间,一棵维护全部的安排,一棵只维护和女神的安排。若基友来约,则直接从全部安排中找时间,若女神来约,则先从全部的找,找不到再从另一棵中找(相当于忽略了基友)。
接下来说怎么找空闲时间:
用1表示空闲0表示有安排。
用 left[i] 表示 i 结点对应区间 [L,R] 中左连续最长空闲时间, right[i] 表示右连续最长空闲时间, middle[i] 表示横跨该结点左右子结点的最长连续空闲时间, maxlen[i] 表示该结点表示区间中的最长空闲时间
对于询问 t,按以下顺序判断:
若 maxlen[i]<t 则此结点无解。
若 left[i]≥t ,则返回 L (空闲时段起点)
若 maxlen[lc]≥t,则向左子树递归,返回其结果。
若 middle[i]≥t ,则返回 mid−right[lc]+1 ,即跨左右子树的起点。
否则 向右子树递归,返回其结果。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define rep(i,f,t) for(int i = (f),_end = (t); i <= _end; ++i)
#define MID int mid = (L+R)>>1;
#define CHD int lc = node<<1, rc = node<<1|1;
const int maxn = 100001<<2;
struct sgt{
int maxlen[maxn];
int left[maxn], middle[maxn], right[maxn];
int setv[maxn];
void init(){
setv[1] = 1;
}
void maintain(int node,int L,int R){
if(setv[node] >= 0){
maxlen[node] = left[node] = right[node] = middle[node] =
(setv[node] ? (R-L+1) : 0);
} else {
CHD;MID;
left[node] = left[lc];
if(left[lc]==(mid-L+1)) left[node] += left[rc];
middle[node] = right[lc]+left[rc];
right[node] = right[rc];
if(right[rc]==R-mid) right[node] += right[lc];
maxlen[node] = max(max(maxlen[lc],maxlen[rc]),middle[node]);
}
}
void pushDown(int node){
if(setv[node] >= 0){
CHD;
setv[lc] = setv[rc] = setv[node];
setv[node] = -1;
}
}
int query(int val,int node,int L,int R){
maintain(node,L,R);
if(val > maxlen[node])return 0; //不在此结点上
if(left[node] >= val)return L; //left
MID;CHD;
pushDown(node);
maintain(rc,mid+1,R); //先维护好右结点信息,方便直接返回
int tmp;
if((tmp=query(val,lc,L,mid))) return tmp; //leftmax
if(middle[node] >= val) return mid-right[lc]+1; //middle
return query(val,rc,mid+1,R); //肯定在右结点上
}
void update(int from,int to,int val,int node,int L,int R){
if(from <= L && R <= to){
setv[node] = val;
}else{
pushDown(node);
MID;CHD;
if(from <= mid) update(from,to,val,lc,L,mid);
else maintain(lc,L,mid);
if(to > mid) update(from,to,val,rc,mid+1,R);
else maintain(rc,mid+1,R);
}
maintain(node,L,R);
}
}ns,all;
int main(){
int T;
scanf("%d",&T);
rep(cas,1,T){
int n,m;
scanf("%d%d",&n,&m);
ns.init();all.init();
printf("Case %d:\n",cas);
while(m--){
char s[10];int a,b;
int ans;
scanf("%s",s);
switch(s[0]){
case 'N':
scanf("%d",&a);
if((ans=all.query(a,1,1,n))||(ans=ns.query(a,1,1,n))){
all.update(ans,ans+a-1,0,1,1,n);
ns.update(ans,ans+a-1,0,1,1,n);
printf("%d,don\'t put my gezi\n",ans);
} else {
printf("wait for me\n");
}
break;
case 'D':
scanf("%d",&a);
ans = all.query(a,1,1,n);
if(ans){
all.update(ans,ans+a-1,0,1,1,n);
printf("%d,let\'s fly\n",ans);
}else{
printf("fly with yourself\n");
}
break;
case 'S':
scanf("%d%d",&a,&b);
all.update(a,b,1,1,1,n);
ns.update(a,b,1,1,1,n);
printf("I am the hope of chinese chengxuyuan!!\n");
break;
}
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。