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