HDU 3308 LCIS 线段树维护区间lcs
2016-05-31 21:45
459 查看
题意:
给一个1~n的数组
操作i把下标为x的值更新为y
操作ii查询区间 x~y的lcs
具体分析写在代码里
///参考讨论版
ACcode:
#include <cstdio>
#include <algorithm>
#define tmp (st<<1)
#define mid ((l+r)>>1)
#define lson l,mid,tmp
#define rson mid+1,r,tmp|1
#define len (r-l+1)
#define maxn 100002
using namespace std;
int my[maxn],sum[maxn<<2],lsum[maxn<<2],rsum[maxn<<2];
inline void push_up(int st,int l,int r){
lsum[st]=lsum[tmp];
rsum[st]=rsum[tmp|1];
sum[st]=max(sum[tmp],sum[tmp|1]);
if(my[mid]<my[mid+1]){///如果第mid+1大于mid 那么对于左子树的右lcs和右子树的左lcs可以合并
if(lsum[st]==len-(len>>1))lsum[st]+=lsum[tmp|1];
if(rsum[st]==len>>1)rsum[st]+=rsum[tmp];
sum[st]=max(sum[st],lsum[tmp|1]+rsum[tmp]);
}
}
inline void build(int l,int r,int st){
if(l==r){
sum[st]=lsum[st]=rsum[st]=1;
return ;
}
build(lson);
build(rson);
push_up(st,l,r);
}
inline void updata(int t,int l,int r,int st){
if(l==r)return ;
if(t<=mid)updata(t,lson);
if(t>mid)updata(t,rson);
push_up(st,l,r);
}
inline int query(int L,int R,int l,int r,int st){
if(L<=l&&r<=R)return sum[st];
if(R<=mid)return query(L,R,lson);
if(L>mid)return query(L,R,rson);
int ans,lans,rans;
lans=query(L,R,lson);
rans=query(L,R,rson);
ans=max(lans,rans);
if(my[mid]<my[mid+1]){///同上
int temp=min(rsum[tmp],mid-L+1)+min(lsum[tmp|1],R-mid);
ans=max(ans,temp);
}
return ans;
}
int main(){
int loop,n,q,x,y;
char str[4];
scanf("%d",&loop);
while(loop--){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i)scanf("%d",&my[i]);
build(1,n,1);
while(q--){
scanf("%s%d%d",str,&x,&y);
if(str[0]=='Q')
printf("%d\n",query(++x,++y,1,n,1));
else{
my[++x]=y;
updata(x,1,n,1);
}
}
}
return 0;
}
给一个1~n的数组
操作i把下标为x的值更新为y
操作ii查询区间 x~y的lcs
具体分析写在代码里
///参考讨论版
ACcode:
#include <cstdio>
#include <algorithm>
#define tmp (st<<1)
#define mid ((l+r)>>1)
#define lson l,mid,tmp
#define rson mid+1,r,tmp|1
#define len (r-l+1)
#define maxn 100002
using namespace std;
int my[maxn],sum[maxn<<2],lsum[maxn<<2],rsum[maxn<<2];
inline void push_up(int st,int l,int r){
lsum[st]=lsum[tmp];
rsum[st]=rsum[tmp|1];
sum[st]=max(sum[tmp],sum[tmp|1]);
if(my[mid]<my[mid+1]){///如果第mid+1大于mid 那么对于左子树的右lcs和右子树的左lcs可以合并
if(lsum[st]==len-(len>>1))lsum[st]+=lsum[tmp|1];
if(rsum[st]==len>>1)rsum[st]+=rsum[tmp];
sum[st]=max(sum[st],lsum[tmp|1]+rsum[tmp]);
}
}
inline void build(int l,int r,int st){
if(l==r){
sum[st]=lsum[st]=rsum[st]=1;
return ;
}
build(lson);
build(rson);
push_up(st,l,r);
}
inline void updata(int t,int l,int r,int st){
if(l==r)return ;
if(t<=mid)updata(t,lson);
if(t>mid)updata(t,rson);
push_up(st,l,r);
}
inline int query(int L,int R,int l,int r,int st){
if(L<=l&&r<=R)return sum[st];
if(R<=mid)return query(L,R,lson);
if(L>mid)return query(L,R,rson);
int ans,lans,rans;
lans=query(L,R,lson);
rans=query(L,R,rson);
ans=max(lans,rans);
if(my[mid]<my[mid+1]){///同上
int temp=min(rsum[tmp],mid-L+1)+min(lsum[tmp|1],R-mid);
ans=max(ans,temp);
}
return ans;
}
int main(){
int loop,n,q,x,y;
char str[4];
scanf("%d",&loop);
while(loop--){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i)scanf("%d",&my[i]);
build(1,n,1);
while(q--){
scanf("%s%d%d",str,&x,&y);
if(str[0]=='Q')
printf("%d\n",query(++x,++y,1,n,1));
else{
my[++x]=y;
updata(x,1,n,1);
}
}
}
return 0;
}
相关文章推荐
- shell中$(( ))与$( )还有${ }的区别
- Tomcat 服务器 Session的实现
- 高版本ubuntu安装低版本arm-linux-gcc
- 强悍的 Linux —— tar
- Linux——》SVN安装
- Linux下coredump调试1:使用
- linux下ssh远程登录/scp远程复制文件/rsync远程同步命令的自动登录
- linux搭建Dubbo控制台
- .net网站的文件上传读取进度条和断点下载
- VS2010工程环境的统一配置
- linux上网问题
- [Shell学习笔记]字符串操作
- Linux is not Matrix——日志搜集平台ELK(III)
- cassandra 监控方案评估
- cassandra 监控方案评估
- Linux Centos的Inode及Block相关知识
- linux 终端常用快捷键
- Linux ssh 下的简单 IM 通信
- 成长历程—基础评教系统维护
- H3C入门配置