LCIS HDU - 3308 (线段树区间合并)
LCIS HDU - 3308
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].
InputT in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
OutputFor 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
个人思路:这道题应该算是线段树区间合并的板子题,关键就是明确区间合并时的逻辑关系就可以了
我因为忽略区间内的最长连续上升序列有可能由子区间的区间内连续上升序列得到而错了好几次
//线段树区间合并
//关键:明确相邻区间合并时候的逻辑关系
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid + 1,r
#define P pair<int,int>
#define ull unsigned long long
using namespace std;
typedef long long ll;
const int maxn = 1e5 + ;
const int inf = 0x3f3f3f3f; struct node
{
int l,r;
int left ,right ,mid;
int maxx;
}tree[maxn << ]; int n,m;
int arr[maxn]; void Pushup(int rt)
{
tree[rt].left = tree[rt << ].left;
tree[rt].right = tree[rt << |].right;
bool flag = arr[tree[rt << |].l] > arr[tree[rt << ].r]; if(tree[rt << |].right == tree[rt << |].r - tree[rt << |].l + && flag)
{
tree[rt].right += tree[rt << ].right;
}
// 合并以左端点为头的最长序列 if(tree[rt << ].left == tree[rt << ].r - tree[rt << ].l + && flag)
{
tree[rt].left += tree[rt << |].left;
}
// 合并以右端点为尾的最长序列 if(arr[tree[rt << |].l] > arr[tree[rt << ].r])
{
tree[rt].mid = tree[rt << ].right + tree[rt << |].left;
}
else
{
tree[rt].mid = max(tree[rt << ].right , tree[rt << |].left);
}
tree[rt].mid = max(tree[rt].mid , max(tree[rt << ].mid,tree[rt << |].mid));
// 获得区间内的最长序列:可能由子区间构成 也可能从子区间得到
tree[rt].maxx = max(tree[rt].mid, max(tree[rt].left , tree[rt].right));
} void build(int rt ,int l ,int r)
{
tree[rt].l = l , tree[rt].r = r;
if(l == r)
{
tree[rt].left = tree[rt].right = tree[rt].maxx = tree[rt].mid = ;
return;
}
int mid = l + r >> ;
build(lson);
build(rson);
Pushup(rt);
} void update(int rt ,int k ,int v)
{
if(tree[rt].l == k && tree[rt].r == k)
{
arr[k] = v;
tree[rt].left = tree[rt].right = tree[rt].maxx = tree[rt].mid = ;
return;
}
int mid = tree[rt].l + tree[rt].r >> ;
if(mid >= k)
{
update(rt << , k , v);
}
else
{
update(rt << | , k , v);
}
Pushup(rt);
} int query(int rt , int l ,int r)
{
if(tree[rt].l == l && tree[rt].r == r)
{
return tree[rt].maxx;
}
int mid = tree[rt].l + tree[rt].r >> ;
if(mid >= r)
{
return query(rt << , l , r);
}
else if(mid < l )
{
return query(rt << | , l , r);
}
else
{
int m = min(mid - l + , tree[rt << ].right) + min(r - mid , tree[rt << |].left);
int left = query(rt<< ,l ,mid);
int right = query(rt << | , mid + , r);
if(arr[tree[rt << ].r] < arr[tree[rt << |].l])
{
return max(m,max(left , right));
}
else
{
return max(left , right);
}
}
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
//mem(arr,0);
scanf("%d %d",&n,&m);
for(int i = ; i <= n ; ++ i)
{
scanf("%d",&arr[i]);
}
build(,,n);
while(m -- )
{
char judge;
int l,r;
scanf(" %c %d %d",&judge ,&l , &r);
if(judge == 'U')
{
update(,l + ,r);
}
else
{
printf("%d\n",query(,l + , r + ));
}
}
}
return ;
}
AC代码
一个从很久以前就开始做的梦
LCIS HDU - 3308 (线段树区间合并)的更多相关文章
- hdu 3308(线段树区间合并)
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 3308 线段树 区间合并+单点更新+区间查询
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 3911 线段树区间合并
北京赛区快了,准备袭击数据结构和图论.倒计时 18天,线段树区间合并.维护一个最长连续.. 题意:给一个01串,以下有一些操作,问区间最长的连续的1的个数 思路:非常裸的线段树区间合并 #includ ...
- hdu 1806(线段树区间合并)
Frequent values Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- HDU 3308 LCIS (线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...
- HDU 3308 (线段树区间合并)
http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意: 两个操作 : 1 修改 单点 a 处的值. 2 求出 区间[a,b]内的最长上升子序列. 做法 ...
- hdu 3911 Black And White (线段树 区间合并)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...
- hdu-3308 LCIS (线段树区间合并)
LCIS Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
随机推荐
- UVA - 548 Tree(二叉树的递归遍历)
题意:已知中序后序序列,求一个叶子到根路径上权和最小,如果多解,则叶子权值尽量小. 分析:已知中序后序建树,再dfs求从根到各叶子的权和比较大小 #include<cstdio> #inc ...
- 10nm Ice Lake处理器值得等待!
处理器.显卡等产品往往习惯先在 Linux 平台测试,所以 Linux 的内核源码往往成为曝光新品的宝藏之地. 经查,在 Linux v5.2 内核最新源码的 x86 分支中,出现了多款 Ice La ...
- 四十、SAP中CASE语句用法
一.上代码 二.选择内容 三.输出 四.我们选择一个其他的值 五.查看输出
- 105-PHP使用var_dump查看类的类型
<?php class ren{ //定义人类 } class mao{ //定义猫类 } $ren1=new ren(); //实例化人类 $mao1=new mao(); //实例化猫类 $ ...
- 通过GlobalAddAtom,GlobalGetAtomName方式发送字符串
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- Python MongoDB 创建数据库
章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...
- 【转载】webdriver 自动化测试如何定位到动态变化ID的iframe框内
大家知道,在自动化测试脚本编写过程中,如果页面上跳出一个iframe框时,我们是定位不到框内内容的,可以通过 driver.findElement(By.id("")); driv ...
- 部署Ambari Server实战案例
部署Ambari Server实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.准备三台虚拟机(需要自行安装jdk环境) 1>.角色分配 NameNode节点: h ...
- js 月份选择器(只选择到月)
需要如下js https://pan.baidu.com/s/1c1T9wY0 在html中添加如下代码 <input onclick="setmonth(this)" /& ...
- JSTL与EL表达式(为空判断)
JSTL与EL表达式(为空判断) 一.循环遍历集合 1.在jsp中引入标准函数声明 <%@ taglib uri="http://java.sun.com/jsp/jstl/cor ...