codeforces #345 (Div. 1) D. Zip-line (线段树+最长上升子序列)
Vasya has decided to build a zip-line on trees of a nearby forest. He wants the line to be as long as possible but he doesn't remember exactly the heights of all trees in the forest. He is sure that he remembers correct heights of all trees except, possibly,
one of them.
It is known that the forest consists of n trees staying in a row numbered from left to right with integers from 1 to n.
According to Vasya, the height of the i-th tree is equal to hi.
The zip-line of length k should hang over k (1 ≤ k ≤ n)
trees i1, i2, ..., ik (i1 < i2 < ... < ik)
such that their heights form an increasing sequence, that is hi1 < hi2 < ... < hik.
Petya had been in this forest together with Vasya, and he now has q assumptions about the mistake in Vasya's sequence h.
His i-th assumption consists of two integers ai and bi indicating
that, according to Petya, the height of the tree numbered ai is
actually equal to bi.
Note that Petya's assumptions are independent from each other.
Your task is to find the maximum length of a zip-line that can be built over the trees under each of the q assumptions.
In this problem the length of a zip line is considered equal to the number of trees that form this zip-line.
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 400 000) —
the number of the trees in the forest and the number of Petya's assumptions, respectively.
The following line contains n integers hi (1 ≤ hi ≤ 109) —
the heights of trees according to Vasya.
Each of the following m lines contains two integers ai and bi (1 ≤ ai ≤ n, 1 ≤ bi ≤ 109).
For each of the Petya's assumptions output one integer, indicating the maximum length of a zip-line that can be built under this assumption.
4 4
1 2 3 4
1 1
1 4
4 3
4 5
4
3
3
4
4 2
1 3 2 6
3 5
2 4
4
3
Consider the first sample. The first assumption actually coincides with the height remembered by Vasya. In the second assumption the heights of the trees are (4, 2, 3, 4),
in the third one they are (1, 2, 3, 3) and in the fourth one they are (1, 2, 3, 5).
题意:给你n个数,有q个询问,每一次替换c上的位置为d,问替换后的最长严格上升子序列的长度是多少。
思路:如果普通的替换再查找肯定超时了,所以我们要用线段树来处理。我们设f[i],g[i]分别为以i位置为尾点和起始点的最长严格上升子序列的长度,这个可以用线段树O(nlogn)的复杂度求出来,记录最长上升子序列的长度为maxlen,然后我们再设f1[i],f2[i]表示询问i替换后,询问替换的位置为c,以c位置为尾点和起始点的最长上升子序列长度。接下来我们要判断替换的节点是不是"关键点","关键点"的意思是,如果原来序列没有这个位置的点,那么原来序列的最长上升子序列的长度达不到maxlen。那么这个要怎么判断呢,我们可以开一个数组cnt[i],表示对于一个节点j,以j为尾节点的最长上升子序列的长度为i,且f[j]+g[j]-1==maxlen的这样符合条件的j点的个数总和。对于每一个位置,先判断f[i]+g[i]-1是不是等于maxlen,如果等于maxlen,那么我们就把cnt[f[i]]++。然后对于每一个询问,ans=max(是不是为关键点?maxlen:maxlen-1
,f1[i]+g1[i]-1 )。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 400050
vector<pair<int,int> >ques[maxn]; //<idx,num>
int ans[maxn],a[maxn],pos[2*maxn];
int f1[maxn],g1[maxn],f[maxn],g[maxn];
int cnt[maxn];
int c[maxn],d[maxn];
struct node1{
struct node{
int l,r,maxlen;
}b[8*maxn];
void build(int l,int r,int th)
{
int mid;
b[th].l=l;b[th].r=r;
b[th].maxlen=0;
if(l==r)return;
mid=(l+r)/2;
build(l,mid,th*2);
build(mid+1,r,th*2+1);
}
int question(int l,int r,int th)
{
int mid;
if(b[th].l==l && b[th].r==r){
return b[th].maxlen;
}
mid=(b[th].l+b[th].r)/2;
if(r<=mid)return question(l,r,th*2);
else if(l>mid)return question(l,r,th*2+1);
return max(question(l,mid,th*2),question(mid+1,r,th*2+1) );
}
void update(int idx,int num,int th)
{
int mid;
if(b[th].l==idx && b[th].r==idx){
b[th].maxlen=num;return;
}
mid=(b[th].l+b[th].r)/2;
if(idx<=mid)update(idx,num,th*2);
else update(idx,num,th*2+1);
b[th].maxlen=max(b[th*2].maxlen,b[th*2+1].maxlen);
}
}L,R;
int main()
{
int n,m,i,j,tot;
while(scanf("%d%d",&n,&m)!=EOF)
{
int tot=0;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
tot++;pos[tot]=a[i];
}
for(i=1;i<=m;i++){
scanf("%d%d",&c[i],&d[i]);
ques[c[i] ].push_back(make_pair(i,d[i] ) );
tot++;pos[tot]=d[i];
}
sort(pos+1,pos+1+tot);
tot=unique(pos+1,pos+1+tot)-pos-1;
L.build(1,tot,1);
R.build(1,tot,1);
int maxlen,num,t;
maxlen=0;
for(i=1;i<=n;i++){
for(j=0;j<ques[i].size();j++){
t=lower_bound(pos+1,pos+1+tot,ques[i][j].second)-pos;
if(t==1)num=1;
else num=L.question(1,t-1,1)+1;
f1[ques[i][j].first ]=num;
}
t=lower_bound(pos+1,pos+1+tot,a[i])-pos;
if(t==1)f[i]=1;
else f[i]=L.question(1,t-1,1)+1;
L.update(t,f[i],1);
maxlen=max(maxlen,f[i]);
}
for(i=n;i>=1;i--){
for(j=0;j<ques[i].size();j++){
t=lower_bound(pos+1,pos+1+tot,ques[i][j].second)-pos;
if(t==tot)num=1;
else num=R.question(t+1,tot,1)+1;
g1[ques[i][j].first ]=num;
}
t=lower_bound(pos+1,pos+1+tot,a[i])-pos;
if(t==tot)g[i]=1;
else g[i]=R.question(t+1,tot,1)+1;
R.update(t,g[i],1);
}
for(i=1;i<=n;i++){
cnt[i]=0;
}
for(i=1;i<=n;i++){
if(f[i]+g[i]-1==maxlen){
cnt[f[i] ]++;
}
}
int ans;
for(i=1;i<=m;i++){
if(f[c[i] ]+g[c[i] ]-1==maxlen && cnt[f[c[i] ] ]==1 ){
ans=maxlen-1;
}
else ans=maxlen;
ans=max(f1[i]+g1[i]-1,ans );
printf("%d\n",ans);
}
}
return 0;
}
/*
15 14
76 9 32 82 40 91 46 5 12 69 44 97 30 13 29
4 73
13 84
14 51
5 99
7 47
14 32
4 12
11 20
9 65
15 95
10 26
5 25
2 62
11 81
*/
codeforces #345 (Div. 1) D. Zip-line (线段树+最长上升子序列)的更多相关文章
- Codeforces #345 Div.1
Codeforces #345 Div.1 打CF有助于提高做题的正确率. Watchmen 题目描述:求欧拉距离等于曼哈顿距离的点对个数. solution 签到题,其实就是求有多少对点在同一行或同 ...
- Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq
B. Prison Transfer Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/pro ...
- Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) F. Souvenirs 线段树套set
F. Souvenirs 题目连接: http://codeforces.com/contest/765/problem/F Description Artsem is on vacation and ...
- Codeforces Round #603 (Div. 2) E. Editor(线段树)
链接: https://codeforces.com/contest/1263/problem/E 题意: The development of a text editor is a hard pro ...
- 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 ...
- Codeforces Round #530 (Div. 2) F (树形dp+线段树)
F. Cookies 链接:http://codeforces.com/contest/1099/problem/F 题意: 给你一棵树,树上有n个节点,每个节点上有ai块饼干,在这个节点上的每块饼干 ...
- Codeforces Round #406 (Div. 2) D. Legacy (线段树建图dij)
D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...
- Codeforces Round #426 (Div. 2) D. The Bakery 线段树优化DP
D. The Bakery Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought req ...
- Codeforces Round #305 (Div. 2) D题 (线段树+RMQ)
D. Mike and Feet time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
随机推荐
- 【Java基础】网络编程
网络编程 网络编程概述 网络编程的目的:直接或简洁地通过网络协议与其他计算机实现数据交换,进行通讯. 网络编程的两个主要问题: 如果准确地定位网络上一台或多台主机,并定位主机上的特定应用: 找到主机后 ...
- 【C++】《C++ Primer 》第十八章
第十八章 用于大型程序的工具 大规模应用程序的特殊要求包括: 在独立开发的子系统之间协同处理错误的能力. 使用各种库进行协同开发的能力. 对比较复杂的应用概念建模的能力. 一.异常处理 异常处理(ex ...
- SpringBoot整合Shiro完成认证
三.SpringBoot整合Shiro思路 首先从客户端发来的所有请求都经过Shiro过滤器,如果用户没有认证的都打回去进行认证,认证成功的,再判断是否具有访问某类资源(公有资源,私有资源)的权限,如 ...
- kubernetes环境部署单节点redis
kubernetes部署redis数据库(单节点) redis简介 Redis 是我们常用的非关系型数据库,在项目开发.测试.部署到生成环境时,经常需要部署一套 Redis 来对数据进行缓存.这里介绍 ...
- python学习笔记 | PyCharm创建文件时自动添加头文件
File Settings Editor File and Code Templates Python Script 然后在右边的框中写入信息就可以啦: # -*- coding: utf-8 -*- ...
- docker 创建数据卷容器
数据卷容器 --volumes-from 容器名/id 先起一个容器 docker run -it --name docker01 centos 然后同步 docker01 的数据卷 --volume ...
- Java JDK8下载 (jdk-8u251-windows-x64和jdk-8u271-linux-x64.tar)
jdk-8u251-windows-x64 和 jdk-8u271-linux-x64.tar 链接:https://pan.baidu.com/s/1gci6aSIFhEhjY8F48qH39Q 提 ...
- Netty学习:伪共享
目录 Netty中的伪共享 伪共享的原理以及介绍 Netty中的伪共享 先说为什么知道这个概念吧,期初看Netty源码的时候,看到了NioEventLoop的构建,其中有这么一句代码: private ...
- 前端开发好帮手,eslint配置全知道
eslint让人又爱又恨,原因在于它的默认配置非常严格,动则一个小提示就直接报错不给运行.而在开发调试的过程中,我们想时时得到运行效果,它的严格又很烦. 在安装eslint后,我们可以在package ...
- [从源码学设计]蚂蚁金服SOFARegistry之延迟操作
[从源码学设计]蚂蚁金服SOFARegistry之延迟操作 0x00 摘要 SOFARegistry 是蚂蚁金服开源的一个生产级.高时效.高可用的服务注册中心. 本系列文章重点在于分析设计和架构,即利 ...