LCIS

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6166    Accepted Submission(s): 2675

Problem Description
Given n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].
 
Input
T in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A B(0<=A<=B< n).
 
Output
For each Q, output the answer.
 
Sample Input
1
10 10
7 7 3 3 5 9 9 8 1 8
Q 6 6
U 3 4
Q 0 1
Q 0 5
Q 4 7
Q 3 5
Q 0 2
Q 4 6
U 6 10
Q 0 9
 
Sample Output
1
1
4
2
3
1
2
5
 
第一道区间合并的线段树。

看了题解,从下午做到晚上。。。然而看网上说是一道简单的区间合并。。。桑心。。。

给出序列,可单点更新,求最长连续递增子列的长度。

每一段记录

struct Node
{
  int l,r,len;  //线段树中的左右端点,以及序列长度
  int ln,rn;   //这个线段上的序列左右端点
  int lm,rm,nm;   //包含左端点,包含右端点,整段的最长递增连续子列长度
} tree[maxn<<2];

一个序列(rt)中的最长连续递增子列的长度(nm)是 max(tree[rt<<1].nm,tree[rt<<1|1].nm)和满足tree[rt<<1].rn<tree[rt<<1|1].ln(左孩子的右端点小于右孩子的左端点)条件下的tree[rt<<1].rm+tree[rt<<1|1].lm中较大者。更新点后pushup和query就是用这个思想。

第一波超时,是因为mid=(l+r)/2,用位运算更快,mid=(l+r)>>1

之前查询函数写的有问题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1 struct Node
{
int l,r,len;
int ln,rn;
int lm,rm,nm;
} tree[maxn<<]; int num[]; void pushup(int rt)
{
tree[rt].ln=tree[rt<<].ln;
tree[rt].rn=tree[rt<<|].rn;
tree[rt].lm=tree[rt<<].lm;
tree[rt].rm=tree[rt<<|].rm;
tree[rt].nm=max(tree[rt<<].nm,tree[rt<<|].nm);
if(tree[rt<<].rn<tree[rt<<|].ln)
{
if(tree[rt].lm==tree[rt<<].len)
tree[rt].lm+=tree[rt<<|].lm;
if(tree[rt].rm==tree[rt<<|].len)
tree[rt].rm+=tree[rt<<].rm;
tree[rt].nm=max(tree[rt].nm,tree[rt<<].rm+tree[rt<<|].lm);
}
} void build(int l,int r,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].len=r-l+;
if(l==r)
{
tree[rt].lm=tree[rt].rm=tree[rt].nm=;
tree[rt].ln=tree[rt].rn=num[l];
return;
}
int mid=(l+r)>>;
build(lson);
build(rson);
pushup(rt);
} void update(int pos,int x,int l,int r,int rt)
{
if(l==pos&&r==pos)
{
tree[rt].ln=tree[rt].rn=x;
return;
}
int mid=(l+r)>>;
if(pos<=mid)
update(pos,x,lson);
else
update(pos,x,rson);
pushup(rt);
} int query(int L,int R,int l,int r,int rt)
{
if(L==l&&r==R)
return tree[rt].nm;
int mid=(l+r)>>;
if(R<=mid)
return query(L,R,lson);
else if(L>mid)
return query(L,R,rson);
else
{
int ll=query(L,mid,lson),ans=;
int rr=query(mid+,R,rson);
if(tree[rt<<].rn<tree[rt<<|].ln)
ans=min(mid-L+,tree[rt<<].rm)+min(R-mid,tree[rt<<|].lm);
return max(ans,max(ll,rr));
}
}
/*
int query(int l,int r,int i)//查询最大的LCIS
{
if(tree[i].l>=l && tree[i].r<=r)
{
return tree[i].nm;
}
int mid = (tree[i].l+tree[i].r)>>1,ans = 0;
if(l<=mid)
ans = max(ans,query(l,r,2*i));
if(r>mid)
ans = max(ans,query(l,r,2*i+1));
if(tree[2*i].rn < tree[2*i+1].ln)
ans = max(ans , min(mid-l+1,tree[2*i].rm)+min(r-mid,tree[2*i+1].lm));
return ans;
}*/ int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=; i<=n; i++)
scanf("%d",&num[i]);
build(,n,);
//cout<<tree[9].nm<<endl;
//cout<<"*"<<endl; for(int i=; i<m; i++)
{
char str[];
int a,b;
scanf("%s%d%d",str,&a,&b);
if(str[]=='U')
update(a+,b,,n,);
else if(str[]=='Q')
printf("%d\n",query(a+,b+,,n,));
}
}
return ;
}

HDU_3308_线段树_区间合并的更多相关文章

  1. 线段树:CDOJ1592-An easy problem B (线段树的区间合并)

    An easy problem B Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  2. 线段树的区间合并 B - LCIS

    B - LCIS HDU - 3308 这个是一个很简单很明显的线段树的区间合并,不过区间合并的题目都还是有点难写,建议存个板子. #include <cstdio> #include & ...

  3. CodeForces - 587E[线段树+线性基+差分] ->(线段树维护区间合并线性基)

    题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 做法一:对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线 ...

  4. Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并

    D. Developing Game   Pavel is going to make a game of his dream. However, he knows that he can't mak ...

  5. 线段树_区间加乘(洛谷P3373模板)

    题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...

  6. [HDOJ3308]LCIS(线段树,区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意:给定n个数,两个操作: U A B:将位置A的数值改成B Q A B:查询[A,B]内最长 ...

  7. POJ 2750 Potted Flower(线段树的区间合并)

    点我看题目链接 题意 : 很多花盆组成的圆圈,每个花盆都有一个值,给你两个数a,b代表a位置原来的数换成b,然后让你从圈里找出连续的各花盆之和,要求最大的. 思路 :这个题比较那啥,差不多可以用DP的 ...

  8. POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并

    看到讲课安排上 线段树有一节课"区间合并" 我是迷茫的 因为并没有见过 然后了解了一下题目 发现以前写过 还是很麻烦的树链剖分 大概是 解决带修改的区间查询"连续问题&q ...

  9. [bzoj2962]序列操作_线段树_区间卷积

    序列操作 bzoj-2962 题目大意:给定一个n个数的正整数序列,m次操作.支持:1.区间加:2.区间取相反数:3.区间求选c个数的乘积和. 注释:$1\le n,m\le 5\cdot 10^4$ ...

随机推荐

  1. java 反射和暴力反射 两个DEMO

    </pre><pre code_snippet_id="402084" snippet_file_name="blog_20140622_5_93502 ...

  2. 《从零開始学Swift》学习笔记(Day 55)——使用try?和try!差别

    原创文章.欢迎转载.转载请注明:关东升的博客   在使用try进行错误处理的时候,常常会看到try后面跟有问号(? )或感叹号(!),他们有什么差别呢? 1.使用try? try?会将错误转换为可选值 ...

  3. SSD性能优化记录

    在上一篇博文中,我设计了一个优化方法,方法从业务角度出发,将切图操作涉及到的性能路径剖析出来,分别进行优化,效果显著. 眼下的情况是:一张ArcGIS武汉市城市影像图.该操作由79小时缩短至当前的67 ...

  4. SOJ.Output the Yanghui triangel

    Output the Yanghui triangel     总提交数量: 225 通过数量: 59                 时间限制:1秒    内存限制:256兆 题目描写叙述 Writ ...

  5. TTS-零基础入门-10分钟教你做一个语音功能

    在本片博客正式開始之前,大家先跟我做一个简单的好玩的 小语音. 新建一个文本文档,然后再文档里输入这样 一句话  CreateObject("SAPI.SpVoice").Spea ...

  6. SQL SERVER:一条SQL语句插入多条记录等

    在学习排名第二的mySql过程中,发现它的插入语句可以这样写: use test; create table fruits( fid char(10) not null ,s_id int null ...

  7. HDU 5858Hard problem

    Hard problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  8. Image图片处理

    public class Imager { #region 正方型裁剪并缩放 /// <summary> /// 正方型裁剪 /// 以图片中心为轴心,截取正方型,然后等比缩放 /// 用 ...

  9. Hybrid 开发

    主讲人:吴彬 要学习某个东西之前,我们首先要了解这个东西是什么?然后我们要了解这东西有什么用,有什么好处和弊端?最后我们要知道这东西怎么用? 简单点就是 ——是什么?有什么用?怎么用? 那么进入正题 ...

  10. bzoj4299

    主席树+脑洞 首先我们有一个结论:如果我们已经凑出1-n,那么下一个数必须小于等于n+1才能凑出n+1,否则结束. 那么如果只有一次询问,我们把数组排序,然后扫一遍看每个数当前能不能加入.但是多组询问 ...