hdu 5367(线段树+区间合并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5367

官方题解:

对于求“高山脉”长度,可以利用线段树。树节点中保存左高度连续长度,左高度连续区间的高度,左高度连续区间的状态(即是否高于第一个高度不同的山),右高度连续长度,右高度连续区间的高度,右高度连续区间的状态,每段区间内的“高山脉”数量。每次更新时更新高度即可,在pushup过程中去计算新产生的“高山脉”。写起来难度不是很大,然后对于n很大且必须在线做这个条件只需对于线段树动态建立节点去维护即可


#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
typedef long long LL;
const int maxn=50010;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int N,Q;
int root,cur;
struct Node
{
    int sum;  //共有多少高山脉
    int ch[2];//左右孩子编号
    int rsum,lsum;//从左边起、从右边起高度相同的连续的有多少个
    int lh,rh;//左边连续、右边连续的高度
    int ll,rr;//左边第一个不连续的,右边第一个不连续的高度
    int add;  
    void init(int l,int r)
    {
        add=sum=lh=rh=ll=rr=ch[0]=ch[1]=0;
        lsum=rsum=r-l+1;
    }
};
struct IntervalTree
{
    Node node[maxn*60];
    void check(int & o,int l,int r)
    {
        if(o)return;
        o=++cur;
        node[o].init(l,r);
        if(l==1)node[o].ll=INF;
        if(r==N)node[o].rr=INF;
    }
    void maintain(int o,int val)
    {
        node[o].add+=val;
        node[o].rr+=val;
        node[o].ll+=val;
        node[o].lh+=val;
        node[o].rh+=val;
    }
    void pushdown(int o,int l,int r)
    {
        if(node[o].add)
        {
            int mid=(l+r)>>1;
            check(node[o].ch[0],l,mid);
            check(node[o].ch[1],mid+1,r);
            maintain(node[o].ch[0],node[o].add);
            maintain(node[o].ch[1],node[o].add);
            node[o].add=0;
        }
    }
    void pushup(int o,int l,int r)
    {
        int mid=(l+r)>>1;
        check(node[o].ch[0],l,mid);
        check(node[o].ch[1],mid+1,r);
        int lson=node[o].ch[0],rson=node[o].ch[1];
        node[o].sum=node[lson].sum+node[rson].sum;
        node[o].lsum=node[lson].lsum;node[o].rsum=node[rson].rsum;
        node[o].lh=node[lson].lh;node[o].rh=node[rson].rh;
        node[o].ll=node[lson].ll;node[o].rr=node[rson].rr;
        if(node[lson].rh==node[rson].lh)
        {
            if(node[lson].rh>node[lson].rr&&node[rson].lh>node[rson].ll)
                node[o].sum+=node[lson].rsum+node[rson].lsum;
            if(node[lson].rsum==mid-l+1)
            {
                node[o].lsum+=node[rson].lsum;
                node[o].ll=node[rson].ll;
            }
            if(node[rson].lsum==r-mid)
            {
                node[o].rsum+=node[lson].rsum;
                node[o].rr=node[lson].rr;
            }
        }
        else
        {
            if(node[lson].lsum==mid-l+1)node[o].ll=node[rson].lh;
            if(node[lson].rh>node[rson].lh&&node[lson].rh>node[lson].rr)
                node[o].sum+=node[lson].rsum;
            if(node[rson].rsum==r-mid)node[o].rr=node[lson].rh;
            if(node[rson].lh>node[lson].rh&&node[rson].lh>node[rson].ll)
                node[o].sum+=node[rson].lsum;
        }
    }
    void update(int &o,int l,int r,int q1,int q2,int x)
    {
        check(o,l,r);
        if(q1<=l&&r<=q2)
        {
            maintain(o,x);
            return ;
        }
        pushdown(o,l,r);
        int mid=(l+r)>>1;
        if(q1<=mid)update(node[o].ch[0],l,mid,q1,q2,x);
        if(q2>mid)update(node[o].ch[1],mid+1,r,q1,q2,x);
        pushup(o,l,r);
    }
}tree;
void solve()
{
    root=cur=0;
    int ans=0;
    int l,r,val;
    for(int i=0;i<Q;i++)
    {
        scanf("%d%d%d",&l,&r,&val);
        l^=ans,r^=ans,val^=ans;
        if(l>r)swap(l,r);
        tree.update(root,1,N,l,r,val);
        ans=tree.node[1].sum;
        printf("%d\n",ans);
    }
}
int main()
{
    while(scanf("%d%d%*d",&N,&Q)!=EOF)
        solve();
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值