hdu4553 约会安排 线段树

  寒假来了,又到了小明和女神们约会的季节。
  小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会。与此同时,也有很多基友找他开黑,由于数量实在过于巨大,怎么安排时间便成了小明的一大心事。
  我们已知小明一共有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!!”,不过小明一般都是三分钟热度,再有人来预定的话,小明就会按耐不住寂寞把学习新知识的时间分配出去。

记录区间最大段的空闲和区间最大段的和基友约的时间,lazy记录被占用或被清除

然后普通的线段树区间操作,分两种查询树上二分查询即可。

 #include<stdio.h>
#include<string.h>
const int maxm=;
const int INF=0x3f3f3f3f; int st[][maxm<<],stl[][maxm<<],str[][maxm<<],stx[][maxm<<];
int la[][maxm<<]; //-1 beizhanyong 1 beiqingchu
int sta;
//nvshen 0 diaosi 1 int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;} void build(int o,int l,int r){
st[][o]=st[][o]=stl[][o]=stl[][o]=str[][o]=str[][o]=r-l+;
stx[][o]=stx[][o]=l;
la[][o]=la[][o]=;
if(l==r)return;
int m=l+((r-l)>>);
build(o<<,l,m);
build(o<<|,m+,r);
} void pushup(int o,int l,int r,int t){
int m=l+((r-l)>>);
if(stl[t][o<<]==m-l+)stl[t][o]=stl[t][o<<]+stl[t][o<<|];
else stl[t][o]=stl[t][o<<];
if(str[t][o<<|]==r-m)str[t][o]=str[t][o<<]+str[t][o<<|];
else str[t][o]=str[t][o<<|];
if(st[t][o<<]>st[t][o<<|]){
st[t][o]=st[t][o<<];
stx[t][o]=stx[t][o<<];
}
else{
st[t][o]=st[t][o<<|];
stx[t][o]=stx[t][o<<|];
}
if(str[t][o<<]+stl[t][o<<|]>st[t][o]){
st[t][o]=str[t][o<<]+stl[t][o<<|];
stx[t][o]=m-str[t][o<<]+;
}
} void pushdown(int o,int l,int r,int t){
if(la[t][o]==-){
la[t][o<<]=la[t][o<<|]=-;
stl[t][o<<]=str[t][o<<]=stl[t][o<<|]=str[t][o<<|]=st[t][o<<]=st[t][o<<|]=;
stx[t][o<<]=stx[t][o<<|]=INF;
la[t][o]=;
}
else if(la[t][o]==){
la[t][o<<]=la[t][o<<|]=;
int m=l+((r-l)>>);
stl[t][o<<]=str[t][o<<]=st[t][o<<]=m-l+;
stl[t][o<<|]=str[t][o<<|]=st[t][o<<|]=r-m;
stx[t][o<<]=l;
stx[t][o<<|]=m+;
la[t][o]=;
}
} void query(int o,int l,int r,int c,int t){
if(st[t][o]>=c)sta=min(sta,stx[t][o]);
else return;
if(l==r)return;
pushdown(o,l,r,t);
int m=l+((r-l)>>);
if(str[t][o<<]+stl[t][o<<|]>=c&&m-str[t][o<<]+<sta)sta=m-str[t][o<<]+;
if(l<sta)query(o<<,l,m,c,t);
if(m+<sta)query(o<<|,m+,r,c,t);
} void update(int o,int l,int r,int ql,int qr,int c,int t){
if(ql<=l&&qr>=r){
if(c==-){
la[t][o]=-;
stl[t][o]=str[t][o]=st[t][o]=;
stx[t][o]=INF;
}
else if(c==){
la[t][o]=;
stl[t][o]=str[t][o]=st[t][o]=r-l+;
stx[t][o]=l;
}
return;
}
pushdown(o,l,r,t);
int m=l+((r-l)>>);
if(ql<=m)update(o<<,l,m,ql,qr,c,t);
if(qr>=m+)update(o<<|,m+,r,ql,qr,c,t);
pushup(o,l,r,t);
} char s[]; int main(){
int T;
scanf("%d",&T);
for(int q=;q<=T;++q){
int n,m;
scanf("%d%d",&n,&m);
printf("Case %d:\n",q);
build(,,n);
for(int i=;i<=m;++i){
scanf("%s",s);
if(s[]=='D'){
int c;
scanf("%d",&c);
sta=INF;
query(,,n,c,);
if(sta==INF)printf("fly with yourself\n");
else{
update(,,n,sta,sta+c-,-,);
printf("%d,let's fly\n",sta);
}
}
else if(s[]=='N'){
int c;
scanf("%d",&c);
sta=INF;
query(,,n,c,);
if(sta==INF){
query(,,n,c,);
if(sta==INF)printf("wait for me\n");
else{
update(,,n,sta,sta+c-,-,);
update(,,n,sta,sta+c-,-,);
printf("%d,don't put my gezi\n",sta);
}
}
else{
update(,,n,sta,sta+c-,-,);
update(,,n,sta,sta+c-,-,);
printf("%d,don't put my gezi\n",sta);
}
}
else if(s[]=='S'){
int a,b;
scanf("%d%d",&a,&b);
update(,,n,a,b,,);
update(,,n,a,b,,);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
}
上一篇:Android 代码自动提示功能


下一篇:Java-集合(没做出来)第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列。 例如: List list = new ArrayList(); list.add(“Hello”); list.add(“World”); list.add(“Learn”); //此时list 为Hello World Learn reverseL