生活随笔
收集整理的這篇文章主要介紹了
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;
}
總結
以上是生活随笔為你收集整理的hdu 5367(线段树+区间合并)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。