您的位置:首页 > 其它

hdu 3308-线段树基本区间合并

2016-04-06 12:22 344 查看
这题明显是线段树基本区间合并,由于第一次写也遇到了不少问题,下面将赘述。。

首先对于区间合并问题,tr里面要有rsum,lsum,msum,分别表示左连续最大,右连续最大,和区间最大,为什么这么表示,当然是为了合并操作。

先说pushup部分,不是简单的sum或者max了,按套路来,如果合并有特殊条件要加特殊条件,对于这道题要加判断arr[mi]和arr[mi+1],

由于这道题没有pushdown,所以还算简单,下一步打算做一个有pushdown的,

queue里面也有技巧,就是当mid在s和t中间时要用min确保合并的时候(当然是符合合并条件时)得到正确答案,以防多算了不在s和t中间的。

midify就是简单的midify加pushup就可以了显而易见。

由于是第一道区间合并还有理解不透彻的地方,希望继续努力,蒟蒻加油。。。

#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
const int MAX=1000000;
struct pr {
int msum,lsum,rsum;
int left,right;
}tr[MAX+10];
int n;
inline int ll(int k) {return 2*k;} //左边的下标
inline int rr(int k) {return 2*k+1;} //右边的下标
inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}
int arr[MAX];

void pushup(int k){//m=r-l+1;
int l=tr[k].left,r=tr[k].right;
int mi=mid(l,r);
tr[k].lsum =tr[ll(k)].lsum;
tr[k].rsum =tr[rr(k)].rsum;//如果合并有条件则加条件
if(arr[mi]<arr[mi+1]){
if (tr[k].lsum == mi-l+1) tr[k].lsum+=tr[rr(k)].lsum;
if (tr[k].rsum == r-mi) tr[k].rsum+=tr[ll(k)].rsum;
tr[k].msum = max(tr[rr(k)].lsum+tr[ll(k)].rsum,max(tr[ll(k)].msum,tr[rr(k)].msum));
return;
}
tr[k].msum = max(tr[ll(k)].msum,tr[rr(k)].msum);
}

void build(int k,int s,int t) {
tr[k].left=s;tr[k].right=t;
if(s==t) {tr[k].lsum=tr[k].rsum=tr[k].msum=1;return;}
build(ll(k),s,mid(s,t));
build(rr(k),mid(s,t)+1,t);
pushup(k); //pushup
return;
}

void modify(int k,int s,int x) {
int l=tr[k].left,r=tr[k].right;
if(l==r){
arr[s]=x;
return ;
}
int mi=mid(l,r);
if(s<=mi) modify(ll(k),s,x);
else if(s>mi) modify(rr(k),s,x);
pushup(k);
}
int query(int k,int s,int t) {
int l=tr[k].left,r=tr[k].right;
if(l==s&&r==t) return tr[k].msum;
int mi=mid(l,r);
int res=0;
if (t<=mi) res=query(ll(k),s,t);
else if(s>mi) res=query(rr(k),s,t);
else {
res=max(query(ll(k),s,mi),query(rr(k),mi+1,t));
if(arr[mi]<arr[mi+1]){
res=max(res,min(mi-s+1,tr[ll(k)].rsum)+min(t-mi,tr[rr(k)].lsum));
}
}
return res;
}

int main(){

int t;
cin>>t;
int n,m;
while(t--){
memset(tr,0,sizeof(tr));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
}
build(1,1,n);
char c[2];
int a,b;
for(int i=0;i<m;i++){
scanf("%s%d%d",c,&a,&b);
if(c[0]=='Q'){
printf("%d\n",query(1,a+1,b+1));
}
else{
modify(1,a+1,b);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: