线段树-hdu-Gangster

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4107

题目大意:

有n个数,m个操作,给一个p,每个操作a,b,c,作用于a~b区间的数,如果该数大于等于p,则该树+2*c,否则+c.求所有操作完成后,数组中的数。

解题思路:

线段树区间更新,lazy标记。

线段树维护一个区间的最大值Max,区间的最小值MIn。以及整个区间增加的值。当Max<p或Min>=p时,直接更新当前区间的add,Max,MIn.否则更新到叶子。

每次更新时,先下传,然后上传更新。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 210000

int p;
struct Node
{
    int Min,Max,add;
}node[Maxn<<2];

void pushup(int rt) //向上更新
{
    node[rt].Min=min(node[rt<<1].Min,node[rt<<1|1].Min);
    node[rt].Max=max(node[rt<<1].Max,node[rt<<1|1].Max);
}
void pushdown(int rt)
{
    if(node[rt].add) //往下更新
    {
        node[rt<<1].add+=node[rt].add;
        node[rt<<1].Max+=node[rt].add;
        node[rt<<1].Min+=node[rt].add;

        node[rt<<1|1].add+=node[rt].add;
        node[rt<<1|1].Max+=node[rt].add;
        node[rt<<1|1].Min+=node[rt].add;

        node[rt].add=0;
    }
}

void build(int l,int r,int rt)
{
    node[rt].Min=node[rt].Max=node[rt].add=0;
    if(l==r)
        return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int l,int r,int rt,int a,int b,int c)
{
   // printf("%d\n",rt);
   // system("pause");
   if(a<=l&&b>=r) //
   {
       if(node[rt].Min>=p) //对整个区间更新
       {
           node[rt].add+=2*c;
           node[rt].Max+=2*c;
           node[rt].Min+=2*c;
           return ;
       }
       if(node[rt].Max<p) //对整个区间更新
       {
           node[rt].add+=c;
           node[rt].Max+=c;
           node[rt].Min+=c;
           return ;
       }
   }
   pushdown(rt); //下传后马上要上传更新
   int m=(l+r)>>1;
   if(a<=m)
        update(lson,a,b,c);
   if(b>m)
        update(rson,a,b,c);
  pushup(rt);

}
void query(int l,int r,int rt)
{
    if(l==r) //从左至右依次输出
    {
        if(l!=1)
            printf(" %d",node[rt].add);
        else
            printf("%d",node[rt].add);
        return ;
    }
    int m=(l+r)>>1;
    pushdown(rt);
    query(lson);
    query(rson);
}

int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   int n,m;
   while(~scanf("%d%d%d",&n,&m,&p))
   {
       build(1,n,1);
       for(int i=1;i<=m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            update(1,n,1,a,b,c);
        }
        query(1,n,1);
        putchar('\n');
   }
   return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值