您的位置:首页 > 其它

hdu 3308 LCIS(单点更新,区间合并)

2011-09-25 19:05 288 查看
题意:给你n个整数,有两种操作,U A B把第A个数变成B,Q A B查询区间[A,B]的最长连续上升序列。

在线段树的节点里保留了端点的值即lval,rval。同时维护左端点最长的上长序列的长度lmx,右端点的最长的下降序列的长度rmx,以及这个区间的最长上升序列的长度mx。在合并区间的时候,如果当前区间的左儿子的lmx等于左儿子的区间长度,那么当前区间的lmx还要加上右儿子的lmx。维护当前区间的rmx也是类似的,当前区间的mx除了在左右儿子的区间中的mx取一个最大值外,还要注意,如果左儿子的右端点小于右儿子的左端点那么当前区间的mx还有可能是左儿子的rmx加上右儿子的lmx。

在查询的时候,要注意,如果查询的范围是在当前区间的左右儿子里,并且左儿子的右端点小于右儿子的左端点,那么不能直接取左儿子的rmx加上右儿子的lmx,因为有可能查询的范围的长度就已经小于左儿子的rmx加上右儿子的lmx,所以要加上一个判断。

(代码风格更新前,没有在线段树节点里保存端点的值)之前做得比较复杂,在节点里还保存了这个区间端点的值,然后在合并的时候去比较,后来在网上看到一种作法,更新到叶子结点的时候直接对数组y进行操作。合并的时候,直接对数组y里的元素进行比较。

/*代码风格更新后*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))
const int N=1e5+5;

struct node
{
int lft,rht;
int lval,rval;
int lmx,rmx,mx;
int mid(){return MID(lft,rht);}
int len(){return rht-lft+1;}
};

int y
,n,m;

struct Segtree
{
node tree[N*4];
void up(int ind)
{
tree[ind].lmx=tree[LL(ind)].lmx;
tree[ind].rmx=tree[RR(ind)].rmx;
tree[ind].lval=tree[LL(ind)].lval;
tree[ind].rval=tree[RR(ind)].rval;
tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx);

if(tree[LL(ind)].rval<tree[RR(ind)].lval)
{
if(tree[LL(ind)].len()==tree[LL(ind)].lmx)
tree[ind].lmx+=tree[RR(ind)].lmx;
if(tree[RR(ind)].len()==tree[RR(ind)].rmx)
tree[ind].rmx+=tree[LL(ind)].rmx;
tree[ind].mx=max(tree[ind].mx,tree[LL(ind)].rmx+tree[RR(ind)].lmx);
}
tree[ind].mx=max(tree[ind].mx,max(tree[ind].lmx,tree[ind].rmx));
}
void build(int lft,int rht,int ind)
{
tree[ind].lft=lft; tree[ind].rht=rht;
if(lft==rht)
{
tree[ind].lval=tree[ind].rval=y[lft];
tree[ind].lmx=tree[ind].rmx=tree[ind].mx=1;
}
else
{
int mid=tree[ind].mid();
build(lft,mid,LL(ind));
build(mid+1,rht,RR(ind));
up(ind);
}
}
void updata(int pos,int ind,int valu)
{
int lft=tree[ind].lft,rht=tree[ind].rht;
if(lft==rht) tree[ind].lval=tree[ind].rval=valu;
else
{
int mid=tree[ind].mid();
if(pos<=mid) updata(pos,LL(ind),valu);
else updata(pos,RR(ind),valu);
up(ind);
}
}
int query(int st,int ed,int ind)
{
int lft=tree[ind].lft,rht=tree[ind].rht;
if(st<=lft&&rht<=ed) return tree[ind].mx;
else
{
int mid=tree[ind].mid();
if(ed<=mid) return query(st,ed,LL(ind));
else if(st>mid) return query(st,ed,RR(ind));
else
{
int tmp1=0,tmp2=0;
int mx1=query(st,ed,LL(ind)),mx2=query(st,ed,RR(ind));
if(tree[LL(ind)].rval<tree[RR(ind)].lval)
{
tmp1=min(mid-st+1,tree[LL(ind)].rmx);
tmp2=min(ed-mid,tree[RR(ind)].lmx);
}
return max(max(mx1,mx2),tmp1+tmp2);
}
}
}
}seg;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&y[i]);
seg.build(0,n-1,1);
while(m--)
{
char cmd[5];
int a,b;
scanf("%s%d%d",cmd,&a,&b);
if(cmd[0]=='Q') printf("%d\n",seg.query(a,b,1));
else seg.updata(a,1,b);
}
}
return 0;
}


/*代码风格更新前*/
#include <iostream>
#include <cstdio>
using namespace std;
const int N=100005;
int y
;
struct node
{
int left,right;
int rmax,lmax,mmax;
int mid(){return left+(right-left)/2;}
int dis(){return right-left+1;}
};
void unin(node &a,node &b,node &c)
{
a.lmax=b.lmax;  a.rmax=c.rmax;
a.mmax=max(b.mmax,c.mmax);
int mid=a.mid();
if(y[mid]<y[mid+1])
{
if(b.lmax==b.dis()) a.lmax+=c.lmax;
if(c.rmax==c.dis()) a.rmax+=b.rmax;
a.mmax=max(a.mmax,b.rmax+c.lmax);
}
}
struct Segtree
{
node tree[N*4];
void build(int left,int right,int r)
{
tree[r].left=left;  tree[r].right=right;
tree[r].rmax=tree[r].lmax=0;
if(left==right)
{
tree[r].lmax=tree[r].rmax=tree[r].mmax=1;
}
else
{
int mid=tree[r].mid();
build(left,mid,r*2);
build(mid+1,right,r*2+1);
unin(tree[r],tree[r*2],tree[r*2+1]);
}
}
void updata(int pos,int r,int co)
{
if(tree[r].left==tree[r].right)
{
y[tree[r].left]=co;
}
else
{
int mid=tree[r].mid();
if(pos<=mid) updata(pos,r*2,co);
else if(pos>mid) updata(pos,r*2+1,co);
unin(tree[r],tree[r*2],tree[r*2+1]);
}
}
int query(int be,int end,int r)
{
if(be<=tree[r].left&&tree[r].right<=end)
{
return tree[r].mmax;
}
else
{
int mid=tree[r].mid();
if(end<=mid) return query(be,end,r*2);
else if(be>mid) return query(be,end,r*2+1);
else
{
int mid=tree[r].mid();
int max1=query(be,end,r*2);
int max2=query(be,end,r*2+1);
if(y[mid]>=y[mid+1]) return max(max1,max2);
else
{
int max3=min(tree[r*2].right-be+1,tree[r*2].rmax)+min(end-tree[r*2+1].left+1,tree[r*2+1].lmax);
return max(max(max1,max2),max3);
}
}
}
}
}seg;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&y[i]);
seg.build(0,n-1,1);
for(int i=0;i<m;i++)
{
char cmd[5];
int a,b;
scanf("%s%d%d",cmd,&a,&b);
if(cmd[0]=='Q')
{
printf("%d\n",seg.query(a,b,1));
}
else if(cmd[0]=='U')
{
seg.updata(a,1,b);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: