HDU 4553 线段树双关键字区间合并

用两个关键字记录,分别为屌丝时间和女神时间

若屌丝约,更新屌丝时间

若女神约,更新屌丝和女神时间

学习,则两个全部清空

#include "stdio.h"
#include "string.h"

struct Data
{
    int l,r,x1,x2,l1,l2,r1,r2;
}data[400010];

int Max(int a,int b)
{
    if (a<b) return b;else return a;
}
void build(int l,int r,int k)
{
    int mid;
    data[k].l=l;
    data[k].r=r;
    data[k].x1=data[k].l1=data[k].r1=r-l+1;
    data[k].x2=data[k].l2=data[k].r2=r-l+1;
    if (l==r) return ;
    mid=(l+r)/2;

    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
}

int query(int x,int k,int op)
{
    if (op==1)
    {
        if (data[k].x1<x) return 0;
        if (data[k].l1>=x) return data[k].l;
        if (data[k*2].x1>=x) return query(x,k*2,op);
        if (data[k*2].r1+data[k*2+1].l1>=x) return data[k*2].r-data[k*2].r1+1;
        return query(x,k*2+1,op);
    }
    if (op==2)
    {
        if (data[k].x2<x) return 0;
        if (data[k].l2>=x) return data[k].l;
        if (data[k*2].x2>=x) return query(x,k*2,op);
        if (data[k*2].r2+data[k*2+1].l2>=x) return data[k*2].r-data[k*2].r2+1;
        return query(x,k*2+1,op);
    }
}

void Pushdown(int k)
{
    int ll,rr,sum;
    if (data[k].l==data[k].r) return ;
    ll=data[k*2].r-data[k*2].l+1;
    rr=data[k*2+1].r-data[k*2+1].l+1;
    sum=data[k].r-data[k].l+1;
    if (data[k].x1==0)
    {
        data[k*2].x1=data[k*2].l1=data[k*2].r1=0;
        data[k*2+1].x1=data[k*2+1].l1=data[k*2+1].r1=0;
    }
    if (data[k].x1==sum)
    {
        data[k*2].x1=data[k*2].l1=data[k*2].r1=ll;
        data[k*2+1].x1=data[k*2+1].l1=data[k*2+1].r1=rr;
    }
    if (data[k].x2==0)
    {
        data[k*2].x2=data[k*2].l2=data[k*2].r2=0;
        data[k*2+1].x2=data[k*2+1].l2=data[k*2+1].r2=0;
    }
    if (data[k].x2==sum)
    {
        data[k*2].x2=data[k*2].l2=data[k*2].r2=ll;
        data[k*2+1].x2=data[k*2+1].l2=data[k*2+1].r2=rr;
    }
}

void Pushup(int k)
{
    int ll,rr;
    ll=data[k*2].r-data[k*2].l+1;
    rr=data[k*2+1].r-data[k*2+1].l+1;

    data[k].l1=data[k*2].l1;
    if (data[k].l1==ll) data[k].l1+=data[k*2+1].l1;
    data[k].r1=data[k*2+1].r1;
    if (data[k].r1==rr) data[k].r1+=data[k*2].r1;
    data[k].x1=Max(Max(data[k*2].x1,data[k*2+1].x1),data[k*2].r1+data[k*2+1].l1);
    data[k].x1=Max(Max(data[k].l1,data[k].r1),data[k].x1);

    data[k].l2=data[k*2].l2;
    if (data[k].l2==ll) data[k].l2+=data[k*2+1].l2;
    data[k].r2=data[k*2+1].r2;
    if (data[k].r2==rr) data[k].r2+=data[k*2].r2;
    data[k].x2=Max(Max(data[k*2].x2,data[k*2+1].x2),data[k*2].r2+data[k*2+1].l2);
    data[k].x2=Max(Max(data[k].l2,data[k].r2),data[k].x2);
}
void updata(int l,int r,int k,int op)
{
    int mid,sum;
    if (data[k].l==l && data[k].r==r)
    {
        sum=data[k].r-data[k].l+1;
        if (op==0)
        {
            data[k].x1=data[k].l1=data[k].r1=sum;
            data[k].x2=data[k].l2=data[k].r2=sum;
            return ;
        }
        if (op==1)
        {
            data[k].x1=data[k].l1=data[k].r1=0;
            return ;
        }
        if (op==2)
        {
            data[k].x1=data[k].l1=data[k].r1=0;
            data[k].x2=data[k].l2=data[k].r2=0;
            return ;
        }
    }

    Pushdown(k);

    mid=(data[k].l+data[k].r)/2;

    if (r<=mid) updata(l,r,k*2,op);
    else
        if (l>mid) updata(l,r,k*2+1,op);
    else
    {
        updata(l,mid,k*2,op);
        updata(mid+1,r,k*2+1,op);
    }
    Pushup(k);
}
int main()
{
    int T,Case,x,y,start,n,m;
    char ch[10];
    scanf("%d",&T);
    Case=0;
    while (T--)
    {
        Case++;
        printf("Case %d:\n",Case);
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while (m--)
        {
            scanf("%s",ch);
            if (ch[0]=='D')
            {
                scanf("%d",&x);
                start=query(x,1,1); // 询问是否有连续x的屌丝时间
                if (start==0)
                    printf("fly with yourself\n");
                else
                {
                    updata(start,start+x-1,1,1); // 从start开始连续x个,更新屌丝时间
                    printf("%d,let's fly\n",start);
                }
            }
            else
            if (ch[0]=='N')
            {
                scanf("%d",&x);
                start=query(x,1,1);
                if (start!=0)
                {
                    updata(start,start+x-1,1,2);
                    printf("%d,don't put my gezi\n",start);
                    continue;
                }
                start=query(x,1,2);// 询问是否有连续x的女神时间
                if (start!=0)
                {
                    updata(start,start+x-1,1,2); // 从start开始连续x个,更新屌丝和女神时间
                    printf("%d,don't put my gezi\n",start);
                    continue;
                }
                printf("wait for me\n");
            }
            else
            {
                scanf("%d%d",&x,&y);
                updata(x,y,1,0); // 更新学习时间
                printf("I am the hope of chinese chengxuyuan!!\n");
            }
        }

    }
    return 0;
}
时间: 2024-10-06 13:20:06

HDU 4553 线段树双关键字区间合并的相关文章

hdu 3308 线段树单点更新 区间合并

http://acm.hdu.edu.cn/showproblem.php?pid=3308 学到两点: 1.以区间端点为开始/结束的最长......似乎在Dp也常用这种思想 2.分类的时候,明确标准逐层分类,思维格式: 条件一成立: { 条件二成立: { } else { } } else { 条件二成立: { } else { } } 上面的这种方式很清晰,如果直接想到那种情况iif(条件一 &条件二)就写,很容易出错而且把自己搞乱,或者情况不全,,,我就因为这WA了几次 3.WA了之后 ,

HDU 3397 线段树 双懒惰标记

这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了 自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了 跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全部置为0或者1,没有置位的时候为-1 还有个rev标记,代表翻转操作,0代表当前不翻,1代表当前翻 要注意一下优先级,发现有不同的弄法,我是这个弄得,有set操作的时候,set标记设值,并把当前节点的rev标记设为0,因为不管要不要rev,当前set操作肯定直接覆盖了 rev操作不改变set操作,在

HDU 1540 Tunnel Warfare(线段树单点更新+区间合并)

Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every vill

HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出对应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  对应区间的LCIS长度(lcis)  对应区间以左端点为起点的LCIS长度(lle)  对应区间以右端点为终点的LCIS长度(lri)  然后用val存储数组对应位置的值  当val[mid + 1] > val[mid] 的时候就要进行区间合并操作了 #include <cstdio> #include <algorithm>

codeforces Good bye 2016 E 线段树维护dp区间合并

题目大意:给你一个字符串,范围为'0'~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问,最少删除多少个字符,使得串中符合ugly串? 思路:定义dp(i, j),其中i=5,j=5,因为只需要删除2016当中其中一个即可,所以一共所需要删除的字符和需要的字符为20176,因此i和j只要5就够了. 然后转移就是dp(i,i) = 0, 如果说区间大小为1的话,那么如果是2017中的一个,那么就是dp(pos, pos+1) = 0, dp(pos,pos) =

POJ 2892 Tunnel Warfare(线段树单点更新区间合并)

Tunnel Warfare Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7876   Accepted: 3259 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally sp

(线段树) (h) poj3667 (区间合并)

poj3667 Hotel 如在阅读本文时遇到不懂的部分,请在评论区询问,或跳转 线段树总介绍 [题目大意] 有一个旅馆,有N个房间排成一排,现在有两种操作,第一是有X个顾客要入住连续的X个房间, 要求输出最小的左端点的位置,不能满足就输出0,第二是将以L开始,长度为X的连续房间清空. [输入文件] 第一行两个数N,M,表示房间数和操作数 接下来M行,每行有两种情况: 1 X 表示操作1 2 L X 表示操作2 [输出文件] 对于每一个1操作,输出答案. 题即为求最靠左的连续区间并置满以及把一段

HDU 3308 线段树单点更新+区间查找最长连续子序列

LCIS                                                              Time Limit: 6000/2000 MS (Java/Others)                                                                 Memory Limit: 65536/32768 K (Java/Others)                                       

hdu 5316 Magician(2015多校第三场第1题)线段树单点更新+区间合并

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5316 题意:给你n个点,m个操作,每次操作有3个整数t,a,b,t表示操作类型,当t=1时讲a点的值改成b:当t=0时,查询区间a,b之间最大的子序列和,这个子序列中的相邻的元素的原来的下标奇偶性都不同. 思路:这道题难点就在查询,其余都是模板,而根据查询,你只要分别把下一个区间的奇偶最大的情况分别比较,合并到上一个区间这样可以构建一个每个节点存有区间中奇开头偶开头,奇结尾,偶结尾这些区间情况的树.