约会安排 HDU - 4553

开两个线段树,分别查询。

注意题面中给出的单引号是中文的,记得要改,不然WA哭。

具体来说,我们开一颗女神树与屌丝树,维护区间和,区间紧靠左右端点的最大值(连续的1),对于屌丝的操作在屌丝树中查找修改,对于女神来说为了不打扰屌丝的时间,我们先在屌丝树中查找时间看是否可以不占用屌丝时间,否则我们再在女神树中找。

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+7;

typedef long long ll;

int sumn[maxn<<2|1];
int lmaxn[maxn<<2|1];
int rmaxn[maxn<<2|1];
int datn[maxn<<2|1];
int lazyn[maxn<<2|1];

int sumd[maxn<<2|1];
int lmaxd[maxn<<2|1];
int rmaxd[maxn<<2|1];
int datd[maxn<<2|1];
int lazyd[maxn<<2|1];

void pushupn(int l,int r,int k){
    int mid=(l+r)>>1;
    sumn[k]=sumn[k<<1]+sumn[k<<1|1];
    lmaxn[k]=lmaxn[k<<1];
    if(sumn[k<<1]==mid-l+1) lmaxn[k]=max(lmaxn[k],sumn[k<<1]+lmaxn[k<<1|1]);
    rmaxn[k]=rmaxn[k<<1|1];
    if(sumn[k<<1|1]==r-mid) rmaxn[k]=max(rmaxn[k],sumn[k<<1|1]+rmaxn[k<<1]);
    datn[k]=max(max(datn[k<<1],datn[k<<1|1]),rmaxn[k<<1]+lmaxn[k<<1|1]);
}

void pushupd(int l,int r,int k){
    int mid=(l+r)>>1;
    sumd[k]=sumd[k<<1]+sumd[k<<1|1];
    lmaxd[k]=lmaxd[k<<1];
    if(sumd[k<<1]==mid-l+1) lmaxd[k]=max(lmaxd[k],sumd[k<<1]+lmaxd[k<<1|1]);
    rmaxd[k]=rmaxd[k<<1|1];
    if(sumd[k<<1|1]==r-mid) rmaxd[k]=max(rmaxd[k],sumd[k<<1|1]+rmaxd[k<<1]);
    datd[k]=max(max(datd[k<<1],datd[k<<1|1]),rmaxd[k<<1]+lmaxd[k<<1|1]);
}

void pushdownn(int l,int r,int k){
    if(lazyn[k]!=-1){
        int mid=(l+r)>>1;
        lazyn[k<<1]=lazyn[k<<1|1]=lazyn[k];
        sumn[k<<1]=lmaxn[k<<1]=rmaxn[k<<1]=datn[k<<1]=(mid-l+1)*lazyn[k];
        sumn[k<<1|1]=lmaxn[k<<1|1]=rmaxn[k<<1|1]=datn[k<<1|1]=(r-mid)*lazyn[k];
        lazyn[k]=-1;
    }
}

void pushdownd(int l,int r,int k){
    if(lazyd[k]!=-1){
        int mid=(l+r)>>1;
        lazyd[k<<1]=lazyd[k<<1|1]=lazyd[k];
        sumd[k<<1]=lmaxd[k<<1]=rmaxd[k<<1]=datd[k<<1]=(mid-l+1)*lazyd[k];
        sumd[k<<1|1]=lmaxd[k<<1|1]=rmaxd[k<<1|1]=datd[k<<1|1]=(r-mid)*lazyd[k];
        lazyd[k]=-1;
    }
}

void build(int l,int r,int k){
    lazyd[k]=lazyn[k]=-1;
    sumn[k]=sumd[k]=datd[k]=datn[k]=lmaxd[k]=lmaxn[k]=rmaxd[k]=rmaxn[k]=r-l+1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
}

//1女,0男;
void updata(int l,int r,int k,int L,int R,int val,int id){
    if(l>=L&&r<=R){
        if(id){
            sumn[k]=lmaxn[k]=rmaxn[k]=datn[k]=(r-l+1)*val;
            lazyn[k]=val;
        }
        else{
            sumd[k]=lmaxd[k]=rmaxd[k]=datd[k]=(r-l+1)*val;
            lazyd[k]=val;
        }
        return ;
    }
    int mid=(l+r)>>1;
    if(id) pushdownn(l,r,k);
    else pushdownd(l,r,k);
    if(L<=mid) updata(l,mid,k<<1,L,R,val,id);
    if(R>mid) updata(mid+1,r,k<<1|1,L,R,val,id);
    if(id) pushupn(l,r,k);
    else pushupd(l,r,k);
}

//1女,0男;
int myfind(int l,int r,int k,int x,int id){
    if(id){
        if(l==r){
            if(x==1&&sumn[k]) return l;
            return 0;
        }
        int mid=(l+r)>>1;
        pushdownn(l,r,k);
        if(datn[k<<1]>=x) return myfind(l,mid,k<<1,x,id);
        else if(rmaxn[k<<1]+lmaxn[k<<1|1]>=x) return mid-rmaxn[k<<1]+1;
        else if(datn[k<<1|1]>=x) return myfind(mid+1,r,k<<1|1,x,id);
        pushupn(l,r,k);
        return 0;
    }
    else{
        if(l==r){
            if(x==1&&sumd[k]) return l;
            return 0;
        }
        int mid=(l+r)>>1;
        pushdownd(l,r,k);
        if(datd[k<<1]>=x) return myfind(l,mid,k<<1,x,id);
        else if(rmaxd[k<<1]+lmaxd[k<<1|1]>=x) return mid-rmaxd[k<<1]+1;
        else if(datd[k<<1|1]>=x) return myfind(mid+1,r,k<<1|1,x,id);
        pushupd(l,r,k);
        return 0;
    }
}


char s[9];
int main(){
    int T,n,q;
    scanf("%d",&T);
    int cc=0;
    int l,r;
    while(T--){
        scanf("%d%d",&n,&q);
        build(1,n,1);
        printf("Case %d:\n",++cc);
        while(q--){
            scanf("%s%d",s,&l);
            if(s[0]=='D'){
                int x=myfind(1,n,1,l,0);
                if(x){
                    updata(1,n,1,x,x+l-1,0,0);
                    printf("%d,let's fly\n",x);
                }
                else{
                    printf("fly with yourself\n");
                }
            }
            else if(s[0]=='N'){
                int x=myfind(1,n,1,l,0);
                if(x){
                    updata(1,n,1,x,x+l-1,0,0);
                    updata(1,n,1,x,x+l-1,0,1);
                    printf("%d,don't put my gezi\n",x);
                }
                else{
                    x=myfind(1,n,1,l,1);
                    if(x){
                        updata(1,n,1,x,x+l-1,0,0);
                        updata(1,n,1,x,x+l-1,0,1);
                        printf("%d,don't put my gezi\n",x);
                    }
                    else{
                        printf("wait for me\n");
                    }
                }
            }
            else if(s[0]=='S'){
                scanf("%d",&r);
                updata(1,n,1,l,r,1,0);
                updata(1,n,1,l,r,1,1);
                printf("I am the hope of chinese chengxuyuan!!\n");
            }
        }
    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值