hdu 3397 Sequence operation(线段树,lazy,区间合并)
2014-05-15 13:29
423 查看
hdu 3397 Sequence operation
线段树lazy和区间合并结合的一个题,相当于几个题集中到一起嘛,分开想就好了
0,1,2操作都要lazy,2的异或操作找到每一只含1或只含0的区间进行取反
3的查询没啥好说的,最基础的求和查询
4的查询要用到区间合并的操作,需要注意的是查询区间跨左右儿子时要考虑跨区间的连续为1的段要在查询区间内
#include<cstdio>
#include<cstring>
#define MAXN 100005
#define lch p<<1
#define rch p<<1|1
//#define mid (t[p].l+t[p].r)>>1
struct node
{
int l,r;
int cover;
int sum;
int mx,lmx,rmx;
//int getlen() {return r-l+1;}
int len;
}t[MAXN<<2];
int max(int a,int b) {return a>b?a:b;}
int min(int a,int b) {return a<b?a:b;}
void pushup(int p)
{
t[p].sum=t[lch].sum+t[rch].sum;
t[p].mx=max(t[lch].mx,t[rch].mx);
t[p].mx=max(t[p].mx,t[lch].rmx+t[rch].lmx);
t[p].lmx=t[lch].lmx;
if(t[lch].lmx==t[lch].len) t[p].lmx+=t[rch].lmx;
t[p].rmx=t[rch].rmx;
if(t[rch].rmx==t[rch].len) t[p].rmx+=t[lch].rmx;
}
void construct(int l,int r,int p)
{
t[p].len=r-l+1;
t[p].l=l,t[p].r=r;
t[p].cover=-1;
if(l==r)
{
scanf("%d",&t[p].mx);
t[p].cover=t[p].lmx=t[p].rmx=t[p].sum=t[p].mx;
return ;
}
int m=(t[p].l+t[p].r)>>1;
construct(l,m,lch);
construct(m+1,r,rch);
pushup(p);
}
void refresh(int p)
{
if(t[p].cover==0)
t[p].mx=t[p].lmx=t[p].rmx=t[p].sum=0;
else
t[p].mx=t[p].lmx=t[p].rmx=t[p].sum=t[p].len;
}
void pushdown(int p)
{
t[lch].cover=t[p].cover;
t[rch].cover=t[p].cover;
refresh(lch);
refresh(rch);
t[p].cover=-1;
}
void modify(int l,int r,int p,int op)
{
if(t[p].l==l&&t[p].r==r)
{
t[p].cover=op;
refresh(p);
return ;
}
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) modify(l,r,lch,op);
else if(l>m) modify(l,r,rch,op);
else modify(l,m,lch,op),modify(m+1,r,rch,op);
pushup(p);
}
void modify_xor(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r&&(t[p].sum==0||t[p].sum==t[p].len))
{
if(t[p].sum) t[p].cover=0;
else t[p].cover=1;
refresh(p);
return ;
}
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) modify_xor(l,r,lch);
else if(l>m) modify_xor(l,r,rch);
else modify_xor(l,m,lch),modify_xor(m+1,r,rch);
pushup(p);
}
int query(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r)
return t[p].sum;
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) return query(l,r,lch);
else if(l>m) return query(l,r,rch);
else return query(l,m,lch)+query(m+1,r,rch);
}
int query_len(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r)
return t[p].mx;
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) return query_len(l,r,lch);
else if(l>m) return query_len(l,r,rch);
else
{
int ans=max(query_len(l,m,lch),query_len(m+1,r,rch));
int lans=min(t[lch].rmx,t[lch].r-l+1),
rans=min(t[rch].lmx,r-t[rch].l+1);
return ans=max(ans,lans+rans);
}
}
int main()
{
int cas,n,m,op,l,r;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
construct(0,n-1,1);
while(m--)
{
scanf("%d%d%d",&op,&l,&r);
if(op==0)
modify(l,r,1,0);
else if(op==1)
modify(l,r,1,1);
else if(op==2)
modify_xor(l,r,1);
else if(op==3)
printf("%d\n",query(l,r,1));
else
printf("%d\n",query_len(l,r,1));
}
}
return 0;
}
线段树lazy和区间合并结合的一个题,相当于几个题集中到一起嘛,分开想就好了
0,1,2操作都要lazy,2的异或操作找到每一只含1或只含0的区间进行取反
3的查询没啥好说的,最基础的求和查询
4的查询要用到区间合并的操作,需要注意的是查询区间跨左右儿子时要考虑跨区间的连续为1的段要在查询区间内
#include<cstdio>
#include<cstring>
#define MAXN 100005
#define lch p<<1
#define rch p<<1|1
//#define mid (t[p].l+t[p].r)>>1
struct node
{
int l,r;
int cover;
int sum;
int mx,lmx,rmx;
//int getlen() {return r-l+1;}
int len;
}t[MAXN<<2];
int max(int a,int b) {return a>b?a:b;}
int min(int a,int b) {return a<b?a:b;}
void pushup(int p)
{
t[p].sum=t[lch].sum+t[rch].sum;
t[p].mx=max(t[lch].mx,t[rch].mx);
t[p].mx=max(t[p].mx,t[lch].rmx+t[rch].lmx);
t[p].lmx=t[lch].lmx;
if(t[lch].lmx==t[lch].len) t[p].lmx+=t[rch].lmx;
t[p].rmx=t[rch].rmx;
if(t[rch].rmx==t[rch].len) t[p].rmx+=t[lch].rmx;
}
void construct(int l,int r,int p)
{
t[p].len=r-l+1;
t[p].l=l,t[p].r=r;
t[p].cover=-1;
if(l==r)
{
scanf("%d",&t[p].mx);
t[p].cover=t[p].lmx=t[p].rmx=t[p].sum=t[p].mx;
return ;
}
int m=(t[p].l+t[p].r)>>1;
construct(l,m,lch);
construct(m+1,r,rch);
pushup(p);
}
void refresh(int p)
{
if(t[p].cover==0)
t[p].mx=t[p].lmx=t[p].rmx=t[p].sum=0;
else
t[p].mx=t[p].lmx=t[p].rmx=t[p].sum=t[p].len;
}
void pushdown(int p)
{
t[lch].cover=t[p].cover;
t[rch].cover=t[p].cover;
refresh(lch);
refresh(rch);
t[p].cover=-1;
}
void modify(int l,int r,int p,int op)
{
if(t[p].l==l&&t[p].r==r)
{
t[p].cover=op;
refresh(p);
return ;
}
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) modify(l,r,lch,op);
else if(l>m) modify(l,r,rch,op);
else modify(l,m,lch,op),modify(m+1,r,rch,op);
pushup(p);
}
void modify_xor(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r&&(t[p].sum==0||t[p].sum==t[p].len))
{
if(t[p].sum) t[p].cover=0;
else t[p].cover=1;
refresh(p);
return ;
}
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) modify_xor(l,r,lch);
else if(l>m) modify_xor(l,r,rch);
else modify_xor(l,m,lch),modify_xor(m+1,r,rch);
pushup(p);
}
int query(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r)
return t[p].sum;
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) return query(l,r,lch);
else if(l>m) return query(l,r,rch);
else return query(l,m,lch)+query(m+1,r,rch);
}
int query_len(int l,int r,int p)
{
if(t[p].l==l&&t[p].r==r)
return t[p].mx;
if(t[p].cover!=-1) pushdown(p);
int m=(t[p].l+t[p].r)>>1;
if(r<=m) return query_len(l,r,lch);
else if(l>m) return query_len(l,r,rch);
else
{
int ans=max(query_len(l,m,lch),query_len(m+1,r,rch));
int lans=min(t[lch].rmx,t[lch].r-l+1),
rans=min(t[rch].lmx,r-t[rch].l+1);
return ans=max(ans,lans+rans);
}
}
int main()
{
int cas,n,m,op,l,r;
scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
construct(0,n-1,1);
while(m--)
{
scanf("%d%d%d",&op,&l,&r);
if(op==0)
modify(l,r,1,0);
else if(op==1)
modify(l,r,1,1);
else if(op==2)
modify_xor(l,r,1);
else if(op==3)
printf("%d\n",query(l,r,1));
else
printf("%d\n",query_len(l,r,1));
}
}
return 0;
}
相关文章推荐
- HDU 3397 - Sequence operation(线段树+区间合并)
- HDU-3397 线段树+区间合并
- HDU 3397 Sequence operation(线段树区间合并+区间修改)
- HDU 3911 Black And White(线段树区间合并+lazy操作)
- HDU 3397 Sequence operation (线段树区间合并入门)
- 【线段树】HDU 3397 Sequence operation 区间合并
- hdu 3397 Sequence operation 线段树 区间更新 区间合并
- 【线段树】HDU 3397 Sequence operation 区间合并
- POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并
- HDU 3397 Sequence operation(线段树的区间合并)
- HDU 3397 线段树区间合并
- M - Sequence operation HDU - 3397 线段树,成段更新,区间合并)
- HDU 3397 Sequence operation(线段树区间合并)
- hdu 3397 Sequence operation(线段树区间覆盖,区间合并)
- HDU 3397——Sequence operation(线段树,区间染色+区间异或+区间合并)
- HDU 3911 Black And White(线段树区间合并+lazy操作)
- HDU 3397 Sequence operation (线段树,成段更新,区间合并)
- HDU 3308【线段树-query:区间最长单调上升序列,update:结点更新,区间合并】
- hdu 3308 LCIS(线段树区间合并)
- hdu 3397 Sequence operation(区间合并)