poj3667_Hotel—线段树区间合并

因为用的都是 int64 所以时间没有那么短,换成int的话应该会小于400ms,该方法应该是时间效率最高的方法,理论上比HH的方法快,任何独立操作都在logn时间完成,而且还有优化~

#include<iostream>

#include<cstdio>
#include<cctype>
using namespace std;
const __int64 maxn=51111;
__int64 lsum[maxn<<2];
__int64 rsum[maxn<<2];
__int64 msum[maxn<<2];
__int64 add[maxn<<2];
__int64 lend[maxn<<2];
__int64 rend[maxn<<2];
__int64 N,M;
__int64 a,b,c,d;
void push_up (__int64 root)
{
lsum[root]=lsum[root<<1];
rsum[root]=rsum[root<<1|1];
if( lsum[root<<1] == rend[root<<1] - lend[root<<1]+1 )
{
lsum[root]+=lsum[root<<1|1];
}
if(rsum[root<<1|1] == rend[root<<1|1]-lend[root<<1|1]+1 )
{
rsum[root]+=rsum[root<<1];
}
msum[root]=max( max( rsum[root<<1] + lsum[root<<1|1] , msum[root<<1] ) , msum[root<<1|1] );
/* cout<<"lsum["<<root<<"]="<<lsum[root]<<endl;
cout<<"rsum["<<root<<"]="<<rsum[root]<<endl;
cout<<"msum["<<root<<"]="<<msum[root]<<endl; */
return ;
}
void push_down_one(__int64 root)
{
if(add[root]==1 )
{
add[root<<1]=1;
add[root<<1|1]=1;
add[root]=0;
lsum[root<<1]=rsum[root<<1]=msum[root<<1]=0;
lsum[root<<1|1]=rsum[root<<1|1]=msum[root<<1|1]=0;
}
return ;
}
void push_down_two(__int64 root)
{
if(add[root]==-1 )
{
add[root<<1]=-1;
add[root<<1|1]=-1;
add[root]=0;
lsum[root<<1]=rsum[root<<1]=msum[root<<1]= rend[root<<1]-lend[root<<1]+1 ;
lsum[root<<1|1]=rsum[root<<1|1]=msum[root<<1|1]= rend[root<<1|1]-lend[root<<1|1]+1 ;
}
return ;
}
__int64 query(__int64 num,__int64 root=1)
{
if(lsum[root] >= num)
{
return lend[root];
}
else if(msum[root] >= num)
{
if( msum[root<<1] >= num )
{
return query( num,root<<1 );
}
else
{
if( rsum[root<<1]+lsum[root<<1|1] >= num )
{
return rend[root<<1]-rsum[root<<1]+1;
}
else
{
return query( num,root<<1|1 );
}
}
}
}
void date_up (__int64 l,__int64 r,__int64 root=1)
{
if(l<=lend[root] && r>= rend[root])
{
add[root]=1;
msum[root]=lsum[root]=rsum[root]=0;
return ;
}
else
{
push_down_two (root);
if( l<=rend[root<<1] && r>=lend[root<<1] )
{
date_up(l,r,root<<1);
}
if( l<=rend[root<<1|1] && r>=lend[root<<1|1] )
{
date_up(l,r,root<<1|1);
}
push_up(root);
return ;
}
}
void date_down(__int64 l,__int64 r ,__int64 root=1)
{
if(l<=lend[root] && r>=rend[root])
{
add[root]=-1;
msum[root]=lsum[root]=rsum[root]=rend[root]-lend[root]+1;
return ;
}
else
{
push_down_one (root);
if(add[root]==-1)
{
return ;
}
if( l<=rend[root<<1] && r>=lend[root<<1] )
{
date_down( l,r,root<<1 );
}
if( l<=rend[root<<1|1] && r>=lend[root<<1|1] )
{
date_down( l,r,root<<1|1 );
}
push_up( root );
return ;
}
}
void build(__int64 l,__int64 r,__int64 root=1)
{
lend[root]=l;
rend[root]=r;
lsum[root]=rsum[root]=msum[root]=r-l+1;
if(l==r)
{
return ;
}
else
{
__int64 mid=(r+l)>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
return ;
}
}
int main()
{
cin>>N>>M;
memset(add,0,sizeof(add));
memset(rend,0,sizeof(rend));
memset(lend,0,sizeof(lend));
build(1,N);
for(int t=1;t<=M;t++)
{
scanf("%I64d",&a);
if(a==1)
{
scanf("%I64d",&b);
if(msum[1]>=b)
{
d=query(b);
date_up(d,d+b-1);
printf("%I64d\n",d);
}
else
{
printf("0\n");
}
}
else
{
scanf("%I64d%I64d",&b,&c);
date_down(b,b+c-1);
}
}
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值