码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4553 约会安排 (两个线段树维护区间)

时间:2019-08-15 18:54:20      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:chinese   cas   type   namespace   更新   space   iostream   else   printf   

include

include

include

include

include

include

include

include

define ll long long

define FOR(i,l,r) for(int i = l ; i <= r ;++i )

define inf 1<<30

define EPS (1e-9)

define lson(p) (p<<1)

define rson(p) (p<<1|1)

using namespace std;
typedef pair<int,int> pii;
const int N = 1e5+30;
int n,m;
struct node{
int l,r;
int lsum,rsum,ssum;
}a[N<<2],b[N<<2];

void push_up(int rt,int l,int r){
int mid = (l+r)>>1;
a[rt].lsum = a[lson(rt)].lsum; // 左子树的左连续空间更新父亲
a[rt].rsum = a[rson(rt)].rsum; // 右子树的右连续空间更新父亲
// 总连续空间为 max(左子树总连续,右子树总连续, 左子树右连续+右子树左连续)
a[rt].ssum = max(max(a[lson(rt)].ssum,a[rson(rt)].ssum),a[lson(rt)].rsum+a[rson(rt)].lsum);
if(a[lson(rt)].lsum == mid-l+1) a[rt].lsum += a[rson(rt)].lsum; // 左子树左连续包含了整个左子树,则父亲的左连续扩充右子树的左连续
if(a[rson(rt)].rsum == r-mid) a[rt].rsum += a[lson(rt)].rsum;
b[rt].lsum = b[lson(rt)].lsum;
b[rt].rsum = b[rson(rt)].rsum;
b[rt].ssum = max(max(b[lson(rt)].ssum,b[rson(rt)].ssum),b[lson(rt)].rsum+b[rson(rt)].lsum);
if(b[lson(rt)].lsum == mid-l+1) b[rt].lsum += b[rson(rt)].lsum;
if(b[rson(rt)].rsum == r-mid) b[rt].rsum += b[lson(rt)].rsum;

}

void push_down(int rt,int l,int r){
int mid = (l+r)>>1;
if(a[rt].ssum == r-l+1){ // 父亲被覆盖 ,子区间也被覆盖
a[lson(rt)].lsum = a[lson(rt)].rsum = a[lson(rt)].ssum = mid-l+1;
a[rson(rt)].lsum = a[rson(rt)].rsum = a[rson(rt)].ssum = r-mid;
}else if(a[rt].ssum == 0){ // 父亲被情空,子区间清空
a[lson(rt)].lsum = a[lson(rt)].rsum = a[lson(rt)].ssum = 0;
a[rson(rt)].lsum = a[rson(rt)].rsum = a[rson(rt)].ssum = 0;
}
if(b[rt].ssum == r-l+1){
b[lson(rt)].lsum = b[lson(rt)].rsum = b[lson(rt)].ssum = mid-l+1;
b[rson(rt)].lsum = b[rson(rt)].rsum = b[rson(rt)].ssum = r-mid;
}else if(b[rt].ssum == 0){
b[lson(rt)].lsum = b[lson(rt)].rsum = b[lson(rt)].ssum = 0;
b[rson(rt)].lsum = b[rson(rt)].rsum = b[rson(rt)].ssum = 0;
}
}

void build(int r,int le,int re){
a[r].lsum = b[r].lsum = (re-le+1);
a[r].rsum = b[r].rsum = (re-le+1);
a[r].ssum = b[r].ssum = (re-le+1);
a[r].l = le,a[r].r = re;
b[r].l = le,b[r].r = re;
if(le==re) return ;
int mid = (le+re)>>1;
build(lson(r),le,mid);
build(rson(r),mid+1,re);
}

void update(int op,int l,int r,int rt){
if(a[rt].l>=l && a[rt].r <=r){
if(op==1){ // ds更新自己
a[rt].lsum = a[rt].rsum = a[rt].ssum = 0;
}else if(op==0){ // ns更新两棵树
a[rt].lsum = a[rt].rsum = a[rt].ssum = 0;
b[rt].lsum = b[rt].rsum = b[rt].ssum = 0;
}else{ // 两棵树清空
a[rt].lsum = a[rt].rsum = a[rt].ssum = a[rt].r-a[rt].l +1;
b[rt].lsum = b[rt].rsum = b[rt].ssum = b[rt].r-b[rt].l +1;
}
return ;
}
int mid = (a[rt].l + a[rt].r)>>1;
push_down(rt,a[rt].l,a[rt].r); // 下方标记
if(l<=mid) update(op,l,r,lson(rt));
if(r>mid) update(op,l,r,rson(rt));
push_up(rt,a[rt].l,a[rt].r); // 上提标记
}

int query(int op,int rt,int len){
if(a[rt].l==a[rt].r) return a[rt].l;
push_down(rt,a[rt].l,a[rt].r);
int mid = (a[rt].l + a[rt].r) >> 1;
if(op){ // ds
if(a[lson(rt)].ssum>=len)
return query(op,lson(rt),len);
else if(a[lson(rt)].rsum + a[rson(rt)].lsum >=len) // 左子树的右区间加右子树的左区间满足
return mid-a[lson(rt)].rsum +1; // 起点一定在左子树
else
return query(op,rson(rt),len);
}else{ // ns
if(b[lson(rt)].ssum>= len)
return query(op,lson(rt),len);
else if(b[lson(rt)].rsum + b[rson(rt)].lsum >=len)
return mid-b[lson(rt)].rsum +1;
else
return query(op,rson(rt),len);
}
}
char op[20];
void solve(int cas){
printf("Case %d:\n",cas);
scanf("%d%d",&n,&m);
build(1,1,n);
int l,r;
FOR(i,1,m){
scanf("%s%d",op,&l);
if(op[0]==‘D‘){
if(a[1].ssum>=l){
int pos = query(1,1,l);
printf("%d,let‘s fly\n",pos);
update(1,pos,pos+l-1,1);
}else{
puts("fly with yourself");
}
}else if(op[0]==‘N‘){
if(a[1].ssum>=l){
int pos = query(1,1,l);
printf("%d,don‘t put my gezi\n",pos);
update(0,pos,pos+l-1,1);
}else if(b[1].ssum>=l){
int pos = query(0,1,l);
printf("%d,don‘t put my gezi\n",pos);
update(0,pos,pos+l-1,1);
}else{
puts("wait for me");
}
}else{
scanf("%d",&r);
update(2,l,r,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
int main(){
int t;
scanf("%d",&t);
for(int i=1;i<=t;++i){
solve(i);
}
return 0;
}

hdu 4553 约会安排 (两个线段树维护区间)

标签:chinese   cas   type   namespace   更新   space   iostream   else   printf   

原文地址:https://www.cnblogs.com/xxrlz/p/11359693.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!