HDU 4553 约会安排(线段树区间合并)


线段树区间合并:

寻找询问区间中满足条件的连续最长区间。

而一个区间连续的最长区间有两种情况:

1、此连续最长区间全在左子树或全在右子树,则sum[t]=max(sum[t<<1],sum[t<<1|1])

2、一部分在左子树,一部分在右子树,则sum[t]=suml[t<<1|1]+sum[t<<1]

因此,我们需要记录每个区间的最长连续区间,从左边第一个孩子开始的最长连续区间,从右边第一个孩子开始的最长连续区间


一般利用结构体


【更新方法:】:

	a[i].ls = a[2*i].ls;//左区间
    a[i].rs = a[2*i+1].rs;//右区间
    a[i].ms = max(max(a[2*i].ms,a[2*i+1].ms),a[2*i].rs+a[2*i+1].ls);//父亲区间内的最大区间必定是,左子树最大区间,右子树最大区间,左右子树合并的中间区间,三者中最大的区间值
    if(a[2*i].ls == a[2*i].r-a[2*i].l+1)//左子树区间满了的话,父亲左区间要加上右孩子的左区间
        a[i].ls += a[2*i+1].ls;
    if(a[2*i+1].rs == a[2*i+1].r-a[2*i+1].l+1)//同理 




本题:

约会安排

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 2029    Accepted Submission(s): 561


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

Input
输入第一行为CASE,表示有CASE组测试数据;
每组数据以两个整数T,N开始,T代表总共的时间,N表示预约请求的个数;
接着的N行,每行表示一个女神或者基友的预约,“NS QT”代表一个女神来找小明约一段长为QT的时间,“DS QT”则代表一个屌丝的长为QT的请求,当然也有可能是小明想学知识了,“STUDY!! L R”代表清空L~R区间内的所有请求。

[Technical Specification]
1. 1 <= CASE <= 30
2. 1 <= T, N <= 100000
3. 1 <= QT <= 110000
4. 1 <= L <= R <=T
 

Output
对于每一个case,第一行先输出“Case C:”代表是第几个case,然后N行,每行对应一个请求的结果(参照描述)。
输出样本(可复制此处):
“X,let's fly”,”fly with yourself”,”X,don't put my gezi”,”wait for me”,”I am the hope of chinese chengxuyuan!!”
 

Sample Input
  
  
1 5 6 DS 3 NS 2 NS 4 STUDY!! 1 5 DS 4 NS 2
 

Sample Output
  
  
Case 1: 1,let's fly 4,don't put my gezi wait for me I am the hope of chinese chengxuyuan!! 1,let's fly 1,don't put my gezi
 

Source



分为3 个层次   学习<  屌丝  <  女神;

根据题意  女神优先级最高:


需要维护的有: 女神左区间最长,右最长,全部  屌丝左最长, 右最长,全部



【代码】

//#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define FIN      freopen("input.txt","r",stdin)
#define FOUT     freopen("output.txt","w",stdout)
#define S1(n)    scanf("%d",&n)
#define SL1(n)   scanf("%I64d",&n)
#define S2(n,m)  scanf("%d%d",&n,&m)
#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)
#define Pr(n)     printf("%d\n",n)
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r

using namespace std;
typedef long long ll;
const double PI=acos(-1);
const int INF=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int MAXN=50005;
const int MOD=1e9+7;
const int mod=1e9+7;
int dir[5][2]={0,1,0,-1,1,0,-1,0};

ll inv[maxn*2];
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);};}
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;}
ll lcm(ll a,ll b){ return b/gcd(a,b)*a;}
ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;}
ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;}
ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;}
ll inv2(ll b){return qpow(b,MOD-2);}

int T,Q;

struct node{
    int n,d,s;
    int nl,nr,na;
    int dl,dr,da;
}tree[MAXN<<2];

void PushUp(int rt,int l,int r)
{
    int mid =(l+r)>>1;

    tree[rt].nl=tree[rt<<1].nl;
    tree[rt].nr=tree[rt<<1|1].nr;
    tree[rt].na=max(max(tree[rt<<1].nr+tree[rt<<1|1].nl,tree[rt<<1].na),tree[rt<<1|1].na);
    if(tree[rt].nl==mid-l+1)
        tree[rt].nl+=tree[rt<<1|1].nl;
    if(tree[rt].nr==r-mid)
        tree[rt].nr+=tree[rt<<1].nr;

    tree[rt].dl=tree[rt<<1].dl;
    tree[rt].dr=tree[rt<<1|1].dr;
    tree[rt].da=max(max(tree[rt<<1].dr+tree[rt<<1|1].dl,tree[rt<<1].da),tree[rt<<1|1].da);
    if(tree[rt].dl==mid-l+1)
        tree[rt].dl+=tree[rt<<1|1].dl;
    if(tree[rt].dr==r-mid)
        tree[rt].dr+=tree[rt<<1].dr;
}

void Study_time(int rt,int l,int r)
{
    tree[rt].s=1;
    tree[rt].n=tree[rt].d=0;
    tree[rt].nl=tree[rt].nr=tree[rt].na=r-l+1; // ×
    tree[rt].dl=tree[rt].dr=tree[rt].da=r-l+1; // ×
}
void Diaosi(int rt)
{
    tree[rt].d = 1;
    tree[rt].dl = tree[rt].dr = tree[rt].da = 0;
}
void Nvshen(int rt)
{
    tree[rt].d=0;
    tree[rt].n=1;
    tree[rt].dl = tree[rt].dr = tree[rt].da = 0;
    tree[rt].nl = tree[rt].nr = tree[rt].na = 0;
}
void PushDown(int rt,int l,int r)
{
    int mid =(l+r)>>1;
    if(tree[rt].s)
    {
        Study_time(lson);
        Study_time(rson);
        tree[rt].s=0;
    }
    if(tree[rt].d)
    {
        Diaosi(rt<<1);
        Diaosi(rt<<1|1);
        tree[rt].d=0;
    }
    if(tree[rt].n)
    {
        Nvshen(rt<<1);
        Nvshen(rt<<1|1);
        tree[rt].n=0;
    }
}

void update_sutdy(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r)
    {
        Study_time(rt,l,r);
        return ;
    }
    int mid=(l+r)>>1;
    PushDown(rt,l,r);

    if(L<=mid)
        update_sutdy(lson,L,R);
    if(R>mid)
        update_sutdy(rson,L,R);
    PushUp(rt,l,r);
}

void update_DandN(int rt,int l,int r,int L,int R,int flag)
{
    if(L<=l&&R>=r)
    {
        if(!flag)
            Diaosi(rt);
        else
            Nvshen(rt);
        return ;
    }
    int mid =(l+r)>>1;
    PushDown(rt,l,r);
    if(L<=mid)
        update_DandN(lson,L,R,flag);
    if(R>mid)
        update_DandN(rson,L,R,flag);
    PushUp(rt,l,r);
}


int query(int rt,int l,int r,int w,int flag)
{
        if(l==r) return l;
        int mid =(l+r)>>1;
        PushDown(rt,l,r);
        if(!flag)
        {
            if(tree[rt<<1].da>=w)
                return query(lson,w,flag);
            else if(tree[rt<<1].dr+tree[rt<<1|1].dl>=w) // ¿ÕÓà
                return mid -tree[rt<<1].dr+1;
            else
                return query(rson,w,flag);
        }
        else
        {
            if(tree[rt<<1].na>=w)
                return  query(lson,w,flag);
            else if((tree[rt<<1].nr+tree[rt<<1|1].nl)>=w)
                return mid-tree[rt<<1].nr+1;
            else
                return query(rson,w,flag);
        }
}

void solve()
{
    char str[120];
    int x;
    while(Q--)
    {
        scanf("%s",str);
        if(str[0]=='D')
        {
          scanf("%d",&x);
          if(tree[1].da<x)
                printf("fly with yourself\n");
          else
          {
              int y= query(1,1,T,x,0);
              update_DandN(1,1,T,y,y+x-1,0);
              printf("%d,let's fly\n",y);
          }
        }
        else if(str[0]=='N')
        {
            scanf("%d",&x);
            if(tree[1].da<x)
            {
                if(tree[1].na<x)
                    printf("wait for me\n");
                else
                {
                    int y= query(1,1,T,x,1);
                    update_DandN(1,1,T,y,y+x-1,1);
                    printf("%d,don't put my gezi\n",y);
                }
            }
            else
            {
                int y= query(1,1,T,x,0);
                update_DandN(1,1,T,y,y+x-1,1);
                printf("%d,don't put my gezi\n", y);
            }
        }
        else
        {
            int y;
            scanf("%d %d",&x,&y);
            update_sutdy(1,1,T,x,y);
            printf("I am the hope of chinese chengxuyuan!!\n");
        }
    }

}
int main()
{
    int t,cont=0;
    cin>>t;
    while(t--)
    {
        S2(T,Q);
        printf("Case %d:\n",++cont);
        update_sutdy(1,1,T,1,T);
        solve();
    }
    return 0;
}


123

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值