HDU-4553-约会安排(线段树维护最长连续区间)
2017-02-02 17:08
399 查看
题目链接:HDU-4553-约会安排
线段树维护最长连续区间,query用来找长度=dur的区间左端点,update更新区间内的ll,rr,mm,ill,irr,imm的值 。
#include<bits\stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+7;
int ll[maxn<<2],rr[maxn<<2],mm[maxn<<2];
int ill[maxn<<2],irr[maxn<<2],imm[maxn<<2];
void build(int rt,int l,int r)
{
ll[rt]=rr[rt]=mm[rt]=r-l+1;
ill[rt]=irr[rt]=imm[rt]=r-l+1;
if(l==r) return ;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void push_up(int rt,int l,int r)
{
int mid=(r+l)>>1;
mm[rt]=max(mm[rt<<1],mm[rt<<1|1]);
mm[rt]=max(mm[rt],rr[rt<<1]+ll[rt<<1|1]);
ll[rt]=ll[rt<<1];
rr[rt]=rr[rt<<1|1];
if(ll[rt]==mid-l+1) ll[rt]+=ll[rt<<1|1];
if(rr[rt]==r-mid) rr[rt]+=rr[rt<<1];
imm[rt]=max(imm[rt<<1],imm[rt<<1|1]);
imm[rt]=max(imm[rt],irr[rt<<1]+ill[rt<<1|1]);
ill[rt]=ill[rt<<1];
irr[rt]=irr[rt<<1|1];
if(ill[rt]==mid-l+1) ill[rt]+=ill[rt<<1|1];
if(irr[rt]==r-mid) irr[rt]+=irr[rt<<1];
}
void push_down(int rt,int l,int r)
{
int mid=(l+r)>>1;
if(mm[rt]==r-l+1)
{
ll[rt<<1]=rr[rt<<1]=mm[rt<<1]=mid-l+1;
ll[rt<<1|1]=rr[rt<<1|1]=mm[rt<<1|1]=r-mid;
}
else if(mm[rt]==0)
{
ll[rt<<1]=rr[rt<<1]=mm[rt<<1]=0;
ll[rt<<1|1]=rr[rt<<1|1]=mm[rt<<1|1]=0;
}
if(imm[rt]==r-l+1)
{
ill[rt<<1]=irr[rt<<1]=imm[rt<<1]=mid-l+1;
ill[rt<<1|1]=irr[rt<<1|1]=imm[rt<<1|1]=r-mid;
}
else if(imm[rt]==0)
{
ill[rt<<1]=irr[rt<<1]=imm[rt<<1]=0;
ill[rt<<1|1]=irr[rt<<1|1]=imm[rt<<1|1]=0;
}
}
// 0---DS 1---NS 2---STUDY
void update(int rt,int l,int r,int ul,int ur,int flag)
{
if(ul<=l&&ur>=r)
{
if(flag==1)
ll[rt]=rr[rt]=mm[rt]=ill[rt]=irr[rt]=imm[rt]=0;
else if(flag==0)
ll[rt]=rr[rt]=mm[rt]=0;
else
ll[rt]=rr[rt]=mm[rt]=ill[rt]=irr[rt]=imm[rt]=r-l+1;
return ;
}
push_down(rt,l,r);
int mid=(l+r)>>1;
if(ul<=mid) update(rt<<1,l,mid,ul,ur,flag);
if(ur>mid) update(rt<<1|1,mid+1,r,ul,ur,flag);
push_up(rt,l,r);
}
// find the left end of a corresponding interval
// 0---DS 1---NS
int query(int rt,int l,int r,int dur,int flag)
{
if(l==r) return l;
int mid=(l+r)>>1;
push_down(rt,l,r);
if(flag)
{
if(imm[rt<<1]>=dur) return query(rt<<1,l,mid,dur,flag);
else if(irr[rt<<1]+ill[rt<<1|1]>=dur) return mid-irr[rt<<1]+1;
else return query(rt<<1|1,mid+1,r,dur,flag);
}
else
{
if(mm[rt<<1]>=dur) return query(rt<<1,l,mid,dur,flag);
else if(rr[rt<<1]+ll[rt<<1|1]>=dur) return mid-rr[rt<<1]+1;
else return query(rt<<1|1,mid+1,r,dur,flag);
}
}
char option[10];
int main()
{
/************
freopen("in.txt","r",stdin);
freopen("out1.txt","w",stdout);
/********************/
int T,kase=0;
int t,n,dur;
scanf("%d",&T);
while(++kase<=T)
{
scanf("%d%d",&t,&n);
printf("Case %d:\n",kase);
build(1,1,t);
for(int i=0;i<n;i++)
{
scanf("%s",option);
if(option[0]=='D')
{
scanf("%d",&dur);
if(mm[1]<dur) puts("fly with yourself");
else
{
int res=query(1,1,t,dur,0);
printf("%d,let's fly\n",res);
update(1,1,t,res,res+dur-1,0);
}
}
else if(option[0]=='N')
{
scanf("%d",&dur);
if(mm[1]>=dur)
{
int res=query(1,1,t,dur,0);
printf("%d,don't put my gezi\n",res);
update(1,1,t,res,res+dur-1,1);
}
else if(imm[1]>=dur)
{
int res=query(1,1,t,dur,1);
printf("%d,don't put my gezi\n",res);
update(1,1,t,res,res+dur-1,1);
}
else
puts("wait for me");
}
else
{
int l,r;
scanf("%d%d",&l,&r);
update(1,1,t,l,r,2);
puts("I am the hope of chinese chengxuyuan!!");
}
}
}
return 0;
}
线段树维护最长连续区间,query用来找长度=dur的区间左端点,update更新区间内的ll,rr,mm,ill,irr,imm的值 。
#include<bits\stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+7;
int ll[maxn<<2],rr[maxn<<2],mm[maxn<<2];
int ill[maxn<<2],irr[maxn<<2],imm[maxn<<2];
void build(int rt,int l,int r)
{
ll[rt]=rr[rt]=mm[rt]=r-l+1;
ill[rt]=irr[rt]=imm[rt]=r-l+1;
if(l==r) return ;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void push_up(int rt,int l,int r)
{
int mid=(r+l)>>1;
mm[rt]=max(mm[rt<<1],mm[rt<<1|1]);
mm[rt]=max(mm[rt],rr[rt<<1]+ll[rt<<1|1]);
ll[rt]=ll[rt<<1];
rr[rt]=rr[rt<<1|1];
if(ll[rt]==mid-l+1) ll[rt]+=ll[rt<<1|1];
if(rr[rt]==r-mid) rr[rt]+=rr[rt<<1];
imm[rt]=max(imm[rt<<1],imm[rt<<1|1]);
imm[rt]=max(imm[rt],irr[rt<<1]+ill[rt<<1|1]);
ill[rt]=ill[rt<<1];
irr[rt]=irr[rt<<1|1];
if(ill[rt]==mid-l+1) ill[rt]+=ill[rt<<1|1];
if(irr[rt]==r-mid) irr[rt]+=irr[rt<<1];
}
void push_down(int rt,int l,int r)
{
int mid=(l+r)>>1;
if(mm[rt]==r-l+1)
{
ll[rt<<1]=rr[rt<<1]=mm[rt<<1]=mid-l+1;
ll[rt<<1|1]=rr[rt<<1|1]=mm[rt<<1|1]=r-mid;
}
else if(mm[rt]==0)
{
ll[rt<<1]=rr[rt<<1]=mm[rt<<1]=0;
ll[rt<<1|1]=rr[rt<<1|1]=mm[rt<<1|1]=0;
}
if(imm[rt]==r-l+1)
{
ill[rt<<1]=irr[rt<<1]=imm[rt<<1]=mid-l+1;
ill[rt<<1|1]=irr[rt<<1|1]=imm[rt<<1|1]=r-mid;
}
else if(imm[rt]==0)
{
ill[rt<<1]=irr[rt<<1]=imm[rt<<1]=0;
ill[rt<<1|1]=irr[rt<<1|1]=imm[rt<<1|1]=0;
}
}
// 0---DS 1---NS 2---STUDY
void update(int rt,int l,int r,int ul,int ur,int flag)
{
if(ul<=l&&ur>=r)
{
if(flag==1)
ll[rt]=rr[rt]=mm[rt]=ill[rt]=irr[rt]=imm[rt]=0;
else if(flag==0)
ll[rt]=rr[rt]=mm[rt]=0;
else
ll[rt]=rr[rt]=mm[rt]=ill[rt]=irr[rt]=imm[rt]=r-l+1;
return ;
}
push_down(rt,l,r);
int mid=(l+r)>>1;
if(ul<=mid) update(rt<<1,l,mid,ul,ur,flag);
if(ur>mid) update(rt<<1|1,mid+1,r,ul,ur,flag);
push_up(rt,l,r);
}
// find the left end of a corresponding interval
// 0---DS 1---NS
int query(int rt,int l,int r,int dur,int flag)
{
if(l==r) return l;
int mid=(l+r)>>1;
push_down(rt,l,r);
if(flag)
{
if(imm[rt<<1]>=dur) return query(rt<<1,l,mid,dur,flag);
else if(irr[rt<<1]+ill[rt<<1|1]>=dur) return mid-irr[rt<<1]+1;
else return query(rt<<1|1,mid+1,r,dur,flag);
}
else
{
if(mm[rt<<1]>=dur) return query(rt<<1,l,mid,dur,flag);
else if(rr[rt<<1]+ll[rt<<1|1]>=dur) return mid-rr[rt<<1]+1;
else return query(rt<<1|1,mid+1,r,dur,flag);
}
}
char option[10];
int main()
{
/************
freopen("in.txt","r",stdin);
freopen("out1.txt","w",stdout);
/********************/
int T,kase=0;
int t,n,dur;
scanf("%d",&T);
while(++kase<=T)
{
scanf("%d%d",&t,&n);
printf("Case %d:\n",kase);
build(1,1,t);
for(int i=0;i<n;i++)
{
scanf("%s",option);
if(option[0]=='D')
{
scanf("%d",&dur);
if(mm[1]<dur) puts("fly with yourself");
else
{
int res=query(1,1,t,dur,0);
printf("%d,let's fly\n",res);
update(1,1,t,res,res+dur-1,0);
}
}
else if(option[0]=='N')
{
scanf("%d",&dur);
if(mm[1]>=dur)
{
int res=query(1,1,t,dur,0);
printf("%d,don't put my gezi\n",res);
update(1,1,t,res,res+dur-1,1);
}
else if(imm[1]>=dur)
{
int res=query(1,1,t,dur,1);
printf("%d,don't put my gezi\n",res);
update(1,1,t,res,res+dur-1,1);
}
else
puts("wait for me");
}
else
{
int l,r;
scanf("%d%d",&l,&r);
update(1,1,t,l,r,2);
puts("I am the hope of chinese chengxuyuan!!");
}
}
}
return 0;
}
相关文章推荐
- hdu 1540 Tunnel Warfare (线段树维护左右最长连续区间)
- HDU - 4553 约会安排 (线段树区间合并)
- HDU - 4553 约会安排(线段树 区间合并)
- HDU-4553 约会安排 线段树区间更新
- HDU 4553 约会安排 (线段树,区间合并)
- HDU 4553 约会安排(线段树区间合并)
- HDU 4553 约会安排 (线段树 -- 区间合并(多种优先级的区间合并) )
- HDU 4553 约会安排(线段树区间合并&优先级)
- 约会安排 - HDU 4553 - 线段树 - 区间合并
- Poj 3667 Hotel + Hdu 4553 约会安排 (线段树最左空区间)
- 【维护区间最长连续子序列 && 线段树 && 区间归并】HDU - 1540 Tunnel Warfare
- hdu 3308 线段树-区间连续最长上升子序列
- HDU 4553 约会安排 [线段树]
- HDU 4553 线段树连续区间
- hdoj 4553 约会安排 【线段树区间合并】
- HDU 3308 LCIS(线段树+区间合并+最长递增连续子串)
- hdu1540(线段树维护连续区间模型)
- hdu4533约会安排 (线段树,段更新,与求最长连续升序子序列的题很类似)
- HDU 4553 约会安排(二维线段树)
- HDU 3308 线段树单点更新+区间查找最长连续子序列