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 ...
随机推荐
- JAVA 怎么链接 SQL Server 数据库(半详细)
哇今天闲着没事准备把前几天链接数据库碰到的问题写到博客,写到一半浏览器切出去了,这个浏览器也没保存,晚上又写了一遍,唉 蛋疼呀╮(╯▽╰)╭!! 说一说连接数据库遇到的问题,唉问题繁多,原来自己刷的精 ...
- H5页面单点登录跳回首页 http url参数转义
在往首页跳的时候因为是单点登录进来的,url后面会带有参数,然后存入会话,所以我要拿到原本存入会话的参数放入url后面 但是返回的时候页面报错了 http://localhost:18086/h5ap ...
- mysql8 安装&问题解决
1.下载:https://dev.mysql.com/downloads/mysql/ 2.安装 1).设置环境变量 MYSQL_HOME D:\env\j2ee\mysql\mysql-8.0.19 ...
- Linux添加虚拟内存 && 修改Linux系统语言
Linux添加虚拟内存 首先执行free -h查看内存状况: total used free shared buff/cache available Mem: 1.8G 570M 76M 8.4M 1 ...
- SpringBoot 系列教程之事务隔离级别知识点小结
SpringBoot 系列教程之事务隔离级别知识点小结 上一篇博文介绍了声明式事务@Transactional的简单使用姿势,最文章的最后给出了这个注解的多个属性,本文将着重放在事务隔离级别的知识点上 ...
- Codeforces Round #616 (Div. 2) 题解
A. Even But Not Even 题意: 定义一个数所有位置的和为偶数它本身不为偶数的数为ebne,现在给你一个数字字符串,你可以删除任意位置上的数字使其变为ebne输出任意改变后的结果,如果 ...
- 想要写好Synthesis Essay,学会审题很重要
很多留学生都不太愿意写synthesis essay,因为它的难度要比其他类型的essay要大得多.写一篇synthesis essay需要有能力消化相关的信息,通过语言组织之后再呈现.虽然这种写作技 ...
- 留学萌新Essay写作须知
Essay是留学生们接触比较多的一项留学生作业,但尽管如此,依旧有部分同学对于essay写作是没有足够的把握的.随着开学季的到来,很多萌新初次接触Essay写作,难免会有很多不懂得地方.所以今天小编就 ...
- SPOJ - AMR11H Array Diversity (排列组合)
题意:给定n个数,求包含最大值和最小值的子集(数字连续)和子序列(数字不连续)的个数. 分析: 1.如果n个数都相同,则子集个数为N * (N + 1) / 2,子序列个数为2N-1. 2.将序列从头 ...
- jquery特效 - 网站水波纹
1,index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...