HDU_3308_线段树_区间合并
LCIS
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6166 Accepted Submission(s): 2675
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].
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).
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
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_线段树_区间合并的更多相关文章
- 线段树:CDOJ1592-An easy problem B (线段树的区间合并)
An easy problem B Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...
- 线段树的区间合并 B - LCIS
B - LCIS HDU - 3308 这个是一个很简单很明显的线段树的区间合并,不过区间合并的题目都还是有点难写,建议存个板子. #include <cstdio> #include & ...
- CodeForces - 587E[线段树+线性基+差分] ->(线段树维护区间合并线性基)
题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 做法一:对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线 ...
- 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 ...
- 线段树_区间加乘(洛谷P3373模板)
题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...
- [HDOJ3308]LCIS(线段树,区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题意:给定n个数,两个操作: U A B:将位置A的数值改成B Q A B:查询[A,B]内最长 ...
- POJ 2750 Potted Flower(线段树的区间合并)
点我看题目链接 题意 : 很多花盆组成的圆圈,每个花盆都有一个值,给你两个数a,b代表a位置原来的数换成b,然后让你从圈里找出连续的各花盆之和,要求最大的. 思路 :这个题比较那啥,差不多可以用DP的 ...
- POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并
看到讲课安排上 线段树有一节课"区间合并" 我是迷茫的 因为并没有见过 然后了解了一下题目 发现以前写过 还是很麻烦的树链剖分 大概是 解决带修改的区间查询"连续问题&q ...
- [bzoj2962]序列操作_线段树_区间卷积
序列操作 bzoj-2962 题目大意:给定一个n个数的正整数序列,m次操作.支持:1.区间加:2.区间取相反数:3.区间求选c个数的乘积和. 注释:$1\le n,m\le 5\cdot 10^4$ ...
随机推荐
- Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)
一.回调函数 为什么首先会讲回调函数呢?因为这个是理解监听器.观察者模式的关键. 什么是回调函数 所谓的回调,用于回调的函数. 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数. ...
- 中间件解析FDMEMTABLE.delta生成SQL的方法
遍历Delta.DataView.Rows,Delta.DataView.Rows是记录的行集,由行组成 TFDDatSRow,即是一行记录的对象 TFDDatSRow的方法: GetData(), ...
- Ndk开发笔记
<pre name="code" class="cpp">ndk开发: 1.编译android本地程序的二种方法.q 2.安装ndk编译工具. 3. ...
- swift 2.0 语法 分支
import UIKit // 注意: Swift中可以不写;号, 但是有一定的前提条件, 一行只有一句代码 // 如果一行有多句代码, 那么;还是必须写 // 注意: Swift变态的地方 ...
- javaScript 检測 能否够连接指定server
本文主要讲述怎样在js里面从多个服务端servlet中找到可用的地址 一般项目部署到生产环境之后会有一个生产网段(就是你能够在家訪问)和一个办公网段(仅仅能在公司才干訪问). 我们的项目部署好了之后, ...
- iconfont 不居中的问题
引用 阿里的 iconfont 发现跟我的文字不居中 页面中实际展示的时候,发现 iconfont 字体飘起来了 原因是:iconfont 的基线跟 文字 的基线不同导致的. 解决办法:给 iconf ...
- SoapUI项目书写自我规范
-->Assertions 判断某个节点存在(_input_name, _button_name) -->Resource 文件夹命名 值去掉红色部分信息 https://mercury- ...
- java使用poi读取doc和docx文件(maven自动导入依赖包)
java使用poi读取doc和docx文件(maven自动导入依赖包) 于是在网上搜寻了一阵之后才发现原来doc文档和excel一样不能用普通的io流的方法来读取,而是也需要用poi,于是进行了一番尝 ...
- [Codeforces 485F] Oppa Funcan Style Remastered
[题目链接] https://codeforces.com/contest/986/problem/F [算法] 不难发现 , 每个人都在且仅在一个简单环中 , 设这些环长的长度分别为 A1, A2 ...
- E20170623-ts
filter n. 滤波器; 滤光器; 滤色镜; [化] 过滤器; mass n. 大量,大多; 块,堆,团; [物理学] 质量; 弥撒曲; assignment n. 分给,分配; 任务, ...