题目大意:给你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. 软件工程-东北师大站-第五次作业(PSP)

    1.本周PSP 2.本周进度条 3.本周累计进度图 代码累计折线图 博文字数累计折线图 4.本周PSP饼状图

  2. P4环境搭建

    P4环境搭建 执行仓库中所有脚本,即可即可安装所有依赖项. GitHub链接 脚本执行顺序:deps,p4c-bm,bmv2,p4c

  3. 福大软工1816 - 404 Note Found选题报告

    目录 NABCD分析引用 N(Need,需求): A(Approach,做法): B(Benefit,好处): C(Competitors,竞争): D(Delivery,交付): 初期 中期 个人贡 ...

  4. GO语言教程(一)Linux( Centos)下Go的安装, 以及HelloWorld

    写在前面: 目前,Go语言已经发布了1.5的版本,已经有不少Go语言相关的书籍和教程了,但是看了一些后,觉得还是应该自己写一套Go语言的教程.给广大学习Go语言的朋友多一种选择.因为,咱写的教程,向来 ...

  5. C++变量内存分配及类型修饰符

    前言 了解C++程序内存分配,有助于深刻理解变量的初始化值以及其生存周期.另外,变量类型修饰符也会影响到变量的初始化值及其生存周期.掌握了不同类型变量的初始化值及其生存周期,能够让我们设计程序时定义变 ...

  6. Robotium之“去哪儿旅行”

    Robotium基于APK自动化测试,只有APK文件,没有源代码. Eclipse 默认的debug keystore可以在Windows->Preferences->Android-&g ...

  7. Viewpoint Meta标签

    移动web Viewpoint常用得设置方式: [布局viewpoint] = [设备宽度] = [度量viewpoint] <meta name="viewport" co ...

  8. 第97天:CSS3渐变和过渡详解

    一.渐变 渐变是CSS3当中比较丰富多彩的一个特性,通过渐变我们可以实现许多炫丽的效果,有效的减少图片的使用数量,并且具有很强的适应性和可扩展性. 可分为线性渐变.径向渐变 1. 线性渐变 (grad ...

  9. 51nod-1222-最小公倍数计数

    题意 给到 \(a,b\) ,求 \[ \sum _{i=a}^b\sum _x\sum _y[x\le y][\text{lcm}(x,y)=i] \] 即最小公倍数在 \([a,b]\) 中的有序 ...

  10. CF487E-Tourists

    题意 给出一个\(n\)个点\(m\)条边的无向图,给出每个点的初始点权,\(q\)次操作: 修改一个点的点权 询问两点间的所有路径中最小点权最小的路径上的最小点权 \(n,m,q\le 10^5,w ...