http://acm.hdu.edu.cn/showproblem.php?pid=5367
区间合并的思路就是保存左起连续段和右起连续段的值与长度 还有左起连续段是否大于它右边第一个元素 右起连续段是否大于它左边第一个元素 这样就能在pushup时算出答案
这题关键是强制在线 不能离散化(写完才发现) 要用动态线段树(不是主席树)解决
动态线段树的各种操作和线段树一样 因为本质还是维护的区间 只是用不到的区间先不管 有点lazy思想的意思
比如n=4时 线段树结构如下
1--------4
1--2 3--4
1 2 3 4
如果我只更新[1,2]区间 在普通线段树中 算上update pushup pushdown 需要用到的区间只有[1,4] [1,2] [3,4] [1,1] [2,2] 并且在update时 这些节点代表的区间长度都在参数中 拿过来直接动态分配一块空间给这些节点就好了 至于[3,3] [4,4]这些暂时用不到的区间根本不用管
lazy就是现用现更新 动态线段树就是现用现离散化 一个道理
using namespace std;
const int maxn=2e5+10;
const int N=0x3f3f3f3f;
struct node
{
int l,r;
int len,left,right,all;
int lval,rval,lflag,rflag;
int laz;
};
node tree[4*maxn];
int n,q,root,num;
void init(int l,int r,int &cur)
{
if(cur!=0) return;
cur=++num;
tree[cur].l=tree[cur].r=0;
tree[cur].len=tree[cur].left=tree[cur].right=r-l+1;
tree[cur].all=0;
tree[cur].lval=tree[cur].rval=tree[cur].lflag=tree[cur].rflag=0;
tree[cur].laz=0;
}
void change(int val,int cur)
{
tree[cur].lval+=val,tree[cur].rval+=val;
tree[cur].laz+=val;
}
void pushup(int l,int r,int cur)
{
int m,lc,rc;
m=(l+r)/2;
init(l,m,tree[cur].l);
init(m+1,r,tree[cur].r);
lc=tree[cur].l,rc=tree[cur].r;
tree[cur].left=tree[lc].left;
if(tree[lc].left==tree[lc].len&&tree[lc].lval==tree[rc].lval) tree[cur].left+=tree[rc].left;
tree[cur].right=tree[rc].right;
if(tree[rc].right==tree[rc].len&&tree[rc].rval==tree[lc].rval) tree[cur].right+=tree[lc].right;
tree[cur].all=tree[lc].all+tree[rc].all;
if(tree[lc].rval==tree[rc].lval){
if(tree[lc].rflag&&tree[rc].lflag) tree[cur].all+=tree[lc].right+tree[rc].left;
}
else if(tree[lc].rval<tree[rc].lval){
if(tree[rc].lflag) tree[cur].all+=tree[rc].left;
}
else{
if(tree[lc].rflag) tree[cur].all+=tree[lc].right;
}
tree[cur].lval=tree[lc].lval,tree[cur].rval=tree[rc].rval;
if(tree[lc].left==tree[lc].len){
if(tree[lc].lval>tree[rc].lval) tree[cur].lflag=1;
else if(tree[lc].lval==tree[rc].lval) tree[cur].lflag=tree[rc].lflag;
else tree[cur].lflag=0;
}
else tree[cur].lflag=tree[lc].lflag;
if(tree[rc].right==tree[rc].len){
if(tree[rc].rval>tree[lc].rval) tree[cur].rflag=1;
else if(tree[rc].rval==tree[lc].rval) tree[cur].rflag=tree[lc].rflag;
else tree[cur].rflag=0;
}
else tree[cur].rflag=tree[rc].rflag;
}
void pushdown(int l,int r,int cur)
{
int m,lc,rc;
m=(l+r)/2;
init(l,m,tree[cur].l);
init(m+1,r,tree[cur].r);
if(tree[cur].laz!=0){
lc=tree[cur].l,rc=tree[cur].r;
change(tree[cur].laz,lc);
change(tree[cur].laz,rc);
tree[cur].laz=0;
}
}
void update(int pl,int pr,int val,int l,int r,int &cur)
{
int m;
init(l,r,cur);
if(pl<=l&&r<=pr){
change(val,cur);
return;
}
pushdown(l,r,cur);
m=(l+r)/2;
if(pl<=m) update(pl,pr,val,l,m,tree[cur].l);
if(pr>m) update(pl,pr,val,m+1,r,tree[cur].r);
pushup(l,r,cur);
}
int main()
{
int l,r,val,ans;
while(scanf("%d%d%*d",&n,&q)!=EOF){
root=num=0;
ans=0;
while(q--){
scanf("%d%d%d",&l,&r,&val);
l^=ans,r^=ans,val^=ans;
if(l>r) swap(l,r);
update(l,r,val,1,n,root);
ans=tree[1].all;
printf("%d\n",ans);
}
}
return 0;
}
/*
5 2 0
1 3 2
1 1 -1
*/