HDU 4107 线段树

给出N个节点,M次操作,和p

每次操作 对l-r区间的每一个节点+c,若节点值>=p,则加2*c;

结点存当前区间伤害最小值,最大值,以及lazy操作。更新到假设最小值大于等于P,或者最大值小于P为止。

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

struct node
{
    int l,r,Min,Max,lazy;
} data[800010];
int p;

int Max(int a,int b)
{
    if (a<b) return b;
    else return a;
}

int Min(int a,int b)
{
    if (a<b) return a;
    else return b;
}

void build(int l,int r,int k)
{
    int mid;
    data[k].l=l;
    data[k].r=r;
    data[k].Min=data[k].Max=data[k].lazy=0;

    if (l==r) return ;

    mid=(l+r)/2;

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

void Pushdown(int k)
{
    if (data[k].l==data[k].r) return ;
    if (data[k].lazy!=0)
    {
        data[k*2].lazy+=data[k].lazy;
        data[k*2].Max+=data[k].lazy;
        data[k*2].Min+=data[k].lazy;
        data[k*2+1].lazy+=data[k].lazy;
        data[k*2+1].Max+=data[k].lazy;
        data[k*2+1].Min+=data[k].lazy;
        data[k].lazy=0;
    }
}
void updata(int l,int r,int k,int op)
{
    int mid;
    if (data[k].l==l && data[k].r==r)
    {
        if (data[k].Max<p)
        {
            data[k].lazy+=op;
            data[k].Max+=op;
            data[k].Min+=op;
            return ;
        }
        if (data[k].Min>=p)
        {
            data[k].lazy+=2*op;
            data[k].Max+=2*op;
            data[k].Min+=2*op;
            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);
    }
    data[k].Max=Max(data[k*2].Max,data[k*2+1].Max);
    data[k].Min=Min(data[k*2].Min,data[k*2+1].Min);
}

void query(int k)
{
    if(data[k].l==data[k].r)
    {
        if (data[k].l!=1)
            printf(" %d",data[k].Max);
        else
            printf("%d",data[k].Max);
        return ;
    }
    Pushdown(k);
    query(k*2);
    query(k*2+1);
}

int main()
{
    int n,m,l,r,x;
    while (scanf("%d%d%d",&n,&m,&p)!=EOF)
    {
        build(1,n,1);
        while (m--)
        {
            scanf("%d%d%d",&l,&r,&x);
            updata(l,r,1,x);
        }
        query(1);
        printf("\n");
    }
    return 0;
}
时间: 2024-11-06 09:14:31

HDU 4107 线段树的相关文章

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

hdu 4893 线段树 --- 也是两个变 类似双标记

http://acm.hdu.edu.cn/showproblem.php?pid=4893 开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对 参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍 #include <cstdio> #include <cstring> #include <a

HDU 4902 线段树||暴力

给定一个序列,两种操作 1:把一段变成x. 2:把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 线段树解法:用lazy标记下即可,优化方法还是很巧妙的, Accepted 4902 515MS 3308K 1941 B C++ #include "stdio.h" #include "string.h" struct node { int l,r,x;// 在叶子节点代表值,树节点代表成端更新的lazy操作. }data[400010]

HDU 4302 线段树单点更新,维护区间最大最小值

http://acm.hdu.edu.cn/showproblem.php?pid=4302 Problem Description Holedox is a small animal which can be considered as one point. It lives in a straight pipe whose length is L. Holedox can only move along the pipe. Cakes may appear anywhere in the p

HDU 3397 线段树 双懒惰标记

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

hdu 2795 线段树--点更新

http://acm.hdu.edu.cn/showproblem.php?pid=2795 多校的第一场和第三场都出现了线段树,比赛期间没做,,这两天先做几道热身下,然后31号之前把那两道多校的线段树都搞了,这是一道热身题 关键是建模: 首先一定看清楚题目构造的场景,看有什么特点--------会发现,如果尽量往左上放置的话,那么由于 the i-th announcement is a rectangle of size 1 * wi.,完全可以对h建立线段树,表示一行,结点里的l,r就表示

HDU 1698 线段树(区间染色)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16255    Accepted Submission(s): 8089 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

HDU 3642 线段树+离散化+扫描线

题意:给你N个长方体的左下角和右上角坐标,问你空间中有多少体积是被大于两个不同的立方体覆盖的.x,y~10^6 z~500 考虑到给的z比较小,所以可以直接枚举z,然后跑二维的扫描线就好. 关于处理被不同的线段覆盖三次的问题,可以维护四个信息,cnt,once,twice,more,然后相互推出结果就好. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #