题目大意:给你n个数,m个操作。

有两种操作:

1.U x y 将数组第x位变为y

2. Q x y 问数组第x位到第y位连续最长子序列的长度。

对于每次询问,输出连续最长子序列的长度

思路:用线段树维护上升序列,每个端点维护:左边连续递增的len,右边连续递增的len,中间连续递增的len,左边val,右边val,和目前的len。然后不断更新即可。

注意:如果左区间的最右边的值小于右区间最左边的值,则有一个待定答案是左儿子的右区间+右儿子的左区间

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
/*
①记录本身内部的序列长度
②要将区间合并的时候,rightson的left区间和leftson的right区间判断条件以后再合并。
如果合并区间是对于两端的值
*/
const int maxn = 1e5 + ;
struct Tree{
int leftlen, rightlen, midlen, leftval, rightval, len;
}tree[maxn << ];
int n, m; inline void pushup(int o){
int lb = o << , rb = o << | ;
int lbval = tree[lb].rightval, rbval = tree[rb].leftval;
bool flag = false;
tree[o].midlen = max(tree[lb].rightlen, max(tree[rb].leftlen, max(tree[lb].midlen, tree[rb].midlen)));
if (lbval < rbval) {
flag = true;
tree[o].midlen = max(tree[lb].rightlen + tree[rb].leftlen, tree[o].midlen);
} tree[o].leftlen = tree[lb].leftlen;
if (tree[lb].rightlen == tree[lb].len && flag) tree[o].leftlen = tree[o].midlen; tree[o].rightlen = tree[rb].rightlen;
if (tree[rb].leftlen == tree[rb].len && flag) tree[o].rightlen = tree[o].midlen;
tree[o].leftval = tree[lb].leftval, tree[o].rightval = tree[rb].rightval;
} void buildtree(int l, int r, int o){
tree[o].len = r - l + ;
if (l == r){
int val; scanf("%d", &val);
tree[o].leftlen = tree[o].rightlen = tree[o].midlen = ;
tree[o].leftval = tree[o].rightval = val;
return ;
}
int mid = (l + r) / ;
if (l <= mid) buildtree(l, mid, o << );
if (r > mid) buildtree(mid + , r, o << | );
pushup(o);
//printf("l = %d r = %d leftlen = %d rightlen = %d midlen = %d\n", l, r, tree[o].leftlen, tree[o].rightlen, tree[o].midlen);
} void update(int pos, int val, int l, int r, int o){
if (pos == l && pos == r){
tree[o].leftval = tree[o].rightval = val; return ;
}
int mid = (l + r) / ;
if (pos <= mid) update(pos, val, l, mid, o << );
if (pos > mid) update(pos, val, mid + , r, o << | );
pushup(o);
} int query(int ql, int qr, int l, int r, int o){
int ans = ;
if (ql <= l && qr >= r){
ans = max(ans, max(tree[o].leftlen, max(tree[o].rightlen, tree[o].midlen)));
return ans;
}
int mid = (l + r) / ;
int t1 = -, t2 = -;
if (mid >= ql){
t1 = query(ql, qr, l, mid, o << );
}
if (mid < qr){
t2 = query(ql, qr, mid + , r, o << | );
}
ans = max(ans, max(t1, t2));
///如果左区间的最右边的值小于右区间最左边的值,则有一个待定答案是左儿子的右区间+右儿子的左区间
if (tree[o << ].rightval < tree[o << | ].leftval && t1 > && t2 > ){
t1 = min(tree[o << ].rightlen, mid - ql + ) + min(tree[o << | ].leftlen, qr - mid);
ans = max(ans, t1);
}
return ans;
} int main(){
int t; cin >> t;
while (t--){
scanf("%d%d", &n, &m);
buildtree(, n, );
for (int i = ; i <= m; i++){
char ch[]; int a, b;
scanf("%s%d%d", ch, &a, &b);
if (ch[] == 'U'){
update(a + , b, , n, );
}
else {
printf("%d\n", query(a + , b + , , n, ));
}
}
}
return ;
}

关键:

感觉和以前的一题CF很像,忘了是哪里的了......

5W次单点修改,求最长的连续上升子序列 HDU 3308的更多相关文章

  1. hdu 3308 线段树,单点更新 求最长连续上升序列长度

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  2. 求最长非降(递增)子序列LIS的长度,及注意事项

    非降序列(Increasing Sequence)例如: (1) 完全递增型序列:S={1,3,6,7,9} (2) 部分存在等于的序列:S={1,3,3,6,9} S的非降子序列:由原序列S的元素组 ...

  3. UVA11572-Unique Snowflakes-(最长不同连续子序列)

    题意:给n个数,求最长不同连续子序列.n<=1e6. 解题过程: 1.记录数据存于数组 2.用左右指针l和r指向这段连续区间 3.右指针往右走,如果遇到没有存在于set集合的数就插入集合 否则左 ...

  4. HDU 4745 Two Rabbits(区间DP,最长非连续回文子串)

    Two Rabbits Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total ...

  5. 【JZOJ4889】【NOIP2016提高A组集训第14场11.12】最长公共回文子序列

    题目描述 YJC最近在学习字符串的有关知识.今天,他遇到了这么一个概念:最长公共回文子序列.一个序列S,如果S是回文的且分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  6. pta 习题集 5-5 最长连续递增子序列 (dp)

    给定一个顺序存储的线性表,请设计一个算法查找该线性表中最长的连续递增子序列.例如,(1,9,2,5,7,3,4,6,8,0)中最长的递增子序列为(3,4,6,8). 输入格式: 输入第1行给出正整数n ...

  7. BNUOJ 4215 最长公共连续子序列

    最长公共连续子序列 Time Limit: 1000ms Memory Limit: 65536KB   64-bit integer IO format: %lld      Java class ...

  8. HDU-1754-I Hate It-线段树-求区间最值和单点修改

    开学新拉的题目,老题重做,思路会稍微比之前清晰,不过这也算是一点点进步了. 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现 ...

  9. hdu_2668 Daydream O(n)求最长不重复子串

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2668 Daydream Time Limit: 2000/1000 MS (Java/Others)  ...

随机推荐

  1. Scrum立会报告+燃尽图 04

    此作业要求参见https://edu.cnblogs.com/campus/nenu/2018fall/homework/2194 一.小组介绍 组长:王一可 组员:范靖旋,王硕,赵佳璐,范洪达,祁玉 ...

  2. RIGHT-BICEP单元测试——“二柱子四则运算升级版”

    RIGHT-BICEP单元测试 ——“二柱子四则运算升级版” ”单元测试“这对于我们来说是一个全新的专业含义,在上了软件工程这门课,并当堂编写了简单的"求一组数中的最大值"函数的单 ...

  3. POJ2528的另一种解法(线段切割)

    题目:Mayor's posters 原文地址 首先本题题意是:有一面墙,被等分为1QW份,一份的宽度为一个单位宽度.现在往墙上贴N张海报,每张海报的宽度是任意 的,但是必定是单位宽度的整数倍,且&l ...

  4. 【第二周】Java实现英语文章词频统计

    1.需求:对于给定的英文文章进行单词频率的统计 2.分析: (1)建立一个如下图所示的数据库表word_frequency用来存放单词和其对应数量 (2)Scanner输入要查询的英文文章存入Stri ...

  5. (十二)Jmeter之Bean Shell的使用(一)

    一.什么是Bean Shell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法; BeanShell是一种松散类型的脚本语言(这点和JS类似); BeanS ...

  6. 【转】Apache httpd.conf配置解释

    转自:http://jafy00.blog.51cto.com/2594646/501373 常用配置指令说明 1. ServerRoot:服务器的基础目录,一般来说它将包含conf/和logs/子目 ...

  7. 关于WPS页面横向问题

    上图 即可进行横向竖向页面设置

  8. JS扫雷原理性代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. jenkin报错hudson.plugins.git.GitExcept

    清除工作空间 转载请注明博客出处:http://www.cnblogs.com/cjh-notes/

  10. BZOJ 2957 楼房重建(线段树区间合并)

    一个显而易见的结论是,这种数字的值是单调递增的.我们修改一个数只会对这个数后面的数造成影响.考虑线段树划分出来的若干线段. 这里有两种情况: 1.某个线段中的最大值小于等于修改的数,那么这个线段的贡献 ...