首页 > 其他分享 >hdu 5367(线段树+区间合并)

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

时间:2023-05-29 18:32:54浏览次数:55  
标签:node hdu ch 5367 ll int 线段 lson rson


题目链接: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;
}




标签:node,hdu,ch,5367,ll,int,线段,lson,rson
From: https://blog.51cto.com/u_16143128/6373500

相关文章

  • hdu 5201(隔板法+容斥原理)
    TheMonkeyKingTimeLimit:8000/4000MS(Java/Others)    MemoryLimit:65536/65536K(Java/Others)ProblemDescriptionnpeaches.Andtherearemmonkeys(includingGoKu),theyarenumberedfrom1tom,GoKu’snumberis1.GoKuwa......
  • hdu 5086(dp)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5086题目大意:给出长度为n的数组,然后要求累计里面的每个子串的和。解题思路:这道题直接枚举肯定不行,所以要找递推关系。假设:{1,2,3,4}为某一个序列,假设我们已经找到了{1,2,3},接下来把{4}加入进去;由于{1,2,3}已经有{1},{2},{3},{1,......
  • hdu 5188(限制01背包)
    zhxandcontestTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/65536K(Java/Others)ProblemDescriptionAsoneofthemostpowerfulbrushesintheworld,zhxusuallytakespartinallkindsofcontests.Oneday,zhxtakespar......
  • hdu 5171(矩阵快速幂)
    GTY'sbirthdaygiftTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/65536K(Java/Others)ProblemDescriptiona,b∈S),andadda+b Input2≤n≤100000,1≤k≤1000000000).Thesecondlinecontainsnelementsai......
  • hdu 5157(manacher+前缀和+树状数组)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5157解题思路:我们可以先用mancher算法对字符串进行处理,把以每个点为中心的回文串半径求出来,然后进行处理。加入对以p为中心的点,从p-r[i]+1~p都是回文串的开头,那么对于每个回文串(开头是j)只要记录结尾从1~j-1的回文串个数,我们可......
  • hdu:第K小的数(构造二分)
    ProblemDescription给定\(n\)个正整数\(a_1,a_2,\dots,a_n\)和\(m\)个正整数\(b_1,b_2,\dots,b_m\)。请在\(n\timesm\)个\(a_i+b_j(1\leqi\leqn,1\leqj\leqm)\)中,找到第\(k\)小的数(不去重)。Input第一行包含一个正整数\(T(1\leqT\leq10)\),表示测试数据的组数。每组......
  • hdu:Ice Cream Tower(构造二分)
    一座高度为k的塔\(b1,b_2,\dots,b_k\)满足\(2b_1\leqb_2,2b_2\leqb_3,2b_3\leqb_4,\dots,2b{k-1}\leqb_k\)你要从中选择一些数来叠很多座高度为\(k\)的塔,问最多能叠多少座塔。Input第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。每组数据第一行包含两个正整数n,k(2......
  • 线段树学习总结
    线段树入门线段树的概念线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组......
  • hdu:序列划分(构造二分)
    ProblemDescription给定\(n\)个正整数\(a_1,a_2,\dots,a_n\),将这个序列从左到右划分成\(m\)段,使得每段至少有一个数。你需要让数字之和最大的那一段的数字和尽可能得小。Input第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。每组数据第一行包含两个正整数n,m(1≤m≤......
  • HDU 1176 免费馅饼(简单动态规划)
    传送门这道题是中文描述的,我相信大家都肯定能够看得懂(滑稽),思路上呢大概就是一个升级版的数塔(点我去看数塔)既然是动态规划问题所以首先肯定要先找出来状态转移方程,我找到的状态转移方程就是a[i][j]+=max(max(a[i+1][j+1],a[i+1][j]),a[i+1][j-1]),其中a[i][j]就是表示第i时刻在k位......