您的位置:首页 > 其它

约会安排---hdu4553(线段树,麻烦的区间覆盖)

2016-04-29 01:10 239 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553
算是poj3667的加强版,建立两颗线段树,一个是DS区间,另一个是NS区间。那么根据题意,如果是DS的请求,那么首先查找DS的区间,如果有满足的区间就更新DS区间,NS的区间不需要更新。如果是NS的请求,首先看DS区间是否有满足的区间,否则查找NS区间,如果有就同时更新DS区间和NS区间。那么可以归纳为,只要是NS的请求,就同时更新两颗线段树,否则只更新DS的线段树。
注意输出要从Output中复制,不然会wa道底,还有就是Up函数中的if顺序不能变;

这两道题写了一天,不过值了,当然如果不是因为有学长的博客在,我一天根本写不出来,学长毕竟是学长;

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define INF 0xfffffff
#define N 110050
#define Lson r<<1
#define Rson r<<1|1

struct SegmentTree
{
int L, R;
bool ns, ds, study;  ///0代表
int lsum[2], rsum[2], sum[2];  ///0是屌丝,1女神;

///lsum区间左边(从L开始)连续最大不被覆盖的值
///rsum区间右边(到R介绍)连续最大不被覆盖的值
///sum整个区间连续最大不被覆盖的值

int Mid() { return (L+R)>>1;}
int len() { return R-L+1; }

void clearPlan(bool x)///清空;
{
if(x)
{
lsum[0] = lsum[1] = len();
rsum[0] = rsum[1] = len();
sum[0] = sum[1] = len();
ns = ds = false; study = true;
}
}

void NS(bool x)///女神;
{
if(x)
{
lsum[0] = lsum[1] = 0;
rsum[0] = rsum[1] = 0;
sum[0] = sum[1] = 0;
ns = true; ds = false;
}
}
void DS(bool x)///屌丝;
{
if(x)
{
lsum[0] = rsum[0] = sum[0] = 0;
ds = true;
}
}
} a[N<<2];

void Build(int r, int L, int R)
{
a[r].L = L, a[r].R = R;
a[r].clearPlan(true);///清空 ;
a[r].ns = a[r].ds = a[r].study = false;

if(L == R)return ;

Build(Lson, L, a[r].Mid());
Build(Rson, a[r].Mid()+1, R);
}

void Up(int r, int who)
{
if(a[r].L != a[r].R)
{
a[r].lsum[who] = a[Lson].lsum[who];
a[r].rsum[who] = a[Rson].rsum[who];

if(a[Lson].lsum[who] == a[Lson].len())
a[r].lsum[who] += a[Rson].lsum[who];
if(a[Rson].rsum[who] == a[Rson].len())
a[r].rsum[who] += a[Lson].rsum[who];

a[r].sum[who] = max(a[Lson].rsum[who] + a[Rson].lsum[who],
max(a[Lson].sum[who], a[Rson].sum[who]));
}
}

void Down(int r)///这个顺序不能反
{
if(a[r].study)
{
a[Lson].clearPlan(true);
a[Rson].clearPlan(true);
a[r].study = false;
}
if(a[r].ns)
{
a[Lson].NS(true);
a[Rson].NS(true);
a[r].ns = a[r].ds = false;
}
if(a[r].ds)
{
a[Lson].DS(true);
a[Rson].DS(true);
a[r].ds = false;
}
}

void Update(int r, int L, int R, int flag)
{
if(a[r].L == L && a[r].R == R)
{
if(flag == 3) a[r].DS(true);
if(flag == 2) a[r].NS(true);
if(flag == 1) a[r].clearPlan(true);

return;
}

Down(r);

if( R <= a[r].Mid())
Update(Lson, L, R, flag);
else if( L > a[r].Mid())
Update(Rson, L, R, flag);
else
{
Update(Lson, L, a[r].Mid(), flag);
Update(Rson, a[r].Mid()+1, R, flag);
}
Up(r, 0);
Up(r, 1);
}

int Query(int r, int num, int who)
{
Down(r);

if(a[r].sum[who] < num) return 0;

if(a[r].lsum[who] >= num) return a[r].L;
if(a[Lson].sum[who] >= num) return Query(Lson, num, who);

if(a[Lson].rsum[who]+a[Rson].lsum[who] >= num)
return a[Lson].R - a[Lson].rsum[who] + 1;
return Query(Rson, num, who);
}

int main()
{
int n, m, T, t = 1, R, L, time;

scanf("%d", &T);
while(T--)
{
scanf("%d %d", &n, &m);
Build(1, 1, n);

printf("Case %d:\n", t++);
while(m--)
{
char s[1100];
scanf("%s", s);
if(s[0] == 'D')
{
scanf("%d", &time);
L = Query(1, time, 0);///屌丝是0;

if( !L )printf("fly with yourself\n");
else
{
Update(1, L, L+time-1, 3);
printf("%d,let's fly\n", L);
}
}
else if(s[0] == 'N')
{
scanf("%d", &time);

L = Query(1, time, 0);///先在屌丝时间里找;当在屌丝时间里没时间时在女神时间里找;
if( !L ) L = Query(1, time, 1);///女神是1;

if( !L )printf("wait for me\n");
else
{
Update(1, L, L+time-1, 2);
printf("%d,don't put my gezi\n", L);
}
}
else
{
scanf("%d %d", &L, &R);
Update(1, L, R, 1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: