hdu 5367 digger(线段树)

题意:连续大小一样的数被称为山,必须在它的左边和右边都有比它矮的山时,它被称为高山,给出q个操作,操作是把区间都加上一个数,输出全部高山的总长度。

做法:线段树,维护下这个区间是否是同一个值(same),是的话同一个大小是多少(val),如果不是同一个值,最左边值大小为多少(zv),右边值大小(yv),以及最左边为sv的连续长度(zsz),右边(ysz),以及最左边的值是不是“半个”山峰(右边值比他小)的标记(zuo),右边(you)。最后还有区间更新的标记flag。

由于n高达10^9,所以我们得动态一下(其实还是静态),每个节点保存下左儿子右儿子即可。

AC代码:

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll __int64
#define ull unsigned __int64
#define eps 1e-8
#define NMAX 2000000000
#define MOD (1<<30)
//#define lson l,mid,rt<<1
//#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
template<class T>
inline void scan_d(T &ret)
{
    char c;
    int flag = 0;
    ret=0;
    while(((c=getchar())<'0'||c>'9')&&c!='-');
    if(c == '-')
    {
        flag = 1;
        c = getchar();
    }
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
    if(flag) ret = -ret;
}
const int maxn = 3000000+10;
struct node
{
    int sum,zsz,zv,ysz,yv,flag,val;
    bool zuo,you;
    bool same;
}T[maxn];

int ncnt;
int lson[maxn],rson[maxn];

int newnode(int big)
{
    T[++ncnt].same = 1;
    T[ncnt].sum = 0;
    T[ncnt].flag = T[ncnt].val = big;
    lson[ncnt] = rson[ncnt] = 0;
    return ncnt;
}

void pushdown(int rt)
{
    int ls = lson[rt];
    if(ls == 0) lson[rt] = newnode(T[rt].flag);
    else if(T[rt].flag)
    {
        T[ls].flag += T[rt].flag;
        if(T[ls].same) T[ls].val += T[rt].flag;
        else
        {
            T[ls].zv += T[rt].flag;
            T[ls].yv += T[rt].flag;
        }
    }
    int rs = rson[rt];
    if(rs == 0) rson[rt] = newnode(T[rt].flag);
    else if(T[rt].flag)
    {
        T[rs].flag += T[rt].flag;
        if(T[rs].same) T[rs].val += T[rt].flag;
        else
        {
            T[rs].zv += T[rt].flag;
            T[rs].yv += T[rt].flag;
        }
    }
    T[rt].flag = 0;
}

void pushup(int l, int r, int rt)
{
    int ls = lson[rt], rs = rson[rt], mid = l+r >> 1;
    if(T[ls].same && T[rs].same)
    {
        T[rt].sum = 0;
        if(T[ls].val == T[rs].val)
        {
            T[rt].same = 1;
            T[rt].val = T[ls].val;
        }
        else
        {
            T[rt].same = 0;
            T[rt].zv = T[ls].val;
            T[rt].yv = T[rs].val;
            if(T[ls].val > T[rs].val)
            {
                T[rt].zuo = 1;
                T[rt].you = 0;
                T[rt].zsz = mid-l+1;
            }
            else
            {
                T[rt].zuo = 0;
                T[rt].you = 1;
                T[rt].ysz = r-mid;
            }
        }
    }
    else if(T[ls].same)
    {
        T[rt].same = 0;
        T[rt].you = T[rs].you;
        T[rt].ysz = T[rs].ysz;
        T[rt].yv = T[rs].yv;
        T[rt].sum = T[rs].sum;
        T[rt].zv = T[ls].val;
        if(T[rs].zv == T[ls].val)
        {
            if(T[rs].zuo)
            {
                T[rt].zuo = 1;
                T[rt].zsz = mid-l+1+T[rs].zsz;
            }
            else T[rt].zuo = 0;
        }
        else if(T[rs].zv < T[ls].val)
        {
            T[rt].zuo = 1;
            T[rt].zsz = mid-l+1;
        }
        else
        {
            T[rt].zuo = 0;
            if(T[rs].zuo) T[rt].sum += T[rs].zsz;
        }
    }
    else if(T[rs].same)
    {
        T[rt].same = 0;
        T[rt].zuo = T[ls].zuo;
        T[rt].zsz = T[ls].zsz;
        T[rt].zv = T[ls].zv;
        T[rt].sum = T[ls].sum;
        T[rt].yv = T[rs].val;
        if(T[ls].yv == T[rs].val)
        {
            if(T[ls].you)
            {
                T[rt].you = 1;
                T[rt].ysz = T[ls].ysz+r-mid;
            }
            else T[rt].you = 0;
        }
        else if(T[ls].yv < T[rs].val)
        {
            T[rt].you = 1;
            T[rt].ysz = r-mid;
        }
        else
        {
            T[rt].you = 0;
            if(T[ls].you) T[rt].sum += T[ls].ysz;
        }
    }
    else
    {
        T[rt].same = 0;
        T[rt].zuo = T[ls].zuo;
        T[rt].zsz = T[ls].zsz;
        T[rt].zv = T[ls].zv;
        T[rt].you = T[rs].you;
        T[rt].ysz = T[rs].ysz;
        T[rt].yv = T[rs].yv;
        T[rt].sum = T[ls].sum+T[rs].sum;
        if(T[ls].yv == T[rs].zv)
        {
            if(T[ls].you && T[rs].zuo) T[rt].sum += T[ls].ysz+T[rs].zsz;
        }
        else if(T[ls].yv > T[rs].zv)
        {
            if(T[ls].you) T[rt].sum += T[ls].ysz;
        }
        else if(T[rs].zuo) T[rt].sum += T[rs].zsz;
    }
}

void update(int L, int R, int k, int l, int r, int rt)
{
    if(L <= l && R >= r)
    {
        T[rt].flag += k;
        if(T[rt].same) T[rt].val += k;
        else
        {
            T[rt].zv += k;
            T[rt].yv += k;
        }
        return;
    }
    pushdown(rt);
    int mid = l+r >> 1;
    if(L <= mid) update(L,R,k,l,mid,lson[rt]);
    if(R > mid) update(L,R,k,mid+1,r,rson[rt]);
    pushup(l,r,rt);
}

int main()
{
#ifdef GLQ
    freopen("input.txt","r",stdin);
//    freopen("o.txt","w",stdout);
#endif
    int n,q,r;
    while(~scanf("%d%d%d",&n,&q,&r))
    {
        ncnt = 0;
        newnode(0);
        int ans = 0;
        while(q--)
        {
            int l,r,val;
            scanf("%d%d%d",&l,&r,&val);
            l ^= ans;
            r ^= ans;
            val ^= ans;
            update(l,r,val,1,n,1);
            ans = T[1].sum;
            printf("%d\n",ans);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值