$ >Codeforces \space 650 D.\ Zip-line<$

题目大意 :

有一个长度为 \(n\) 的序列 \(h\) ,\(m\) 次询问,每一次询问求如果把序列中第 \(x\) 元素变成 \(y\) 后的 \(lis\) 长度

\(1 \leq n, m \leq 4 \times 10^5\)

解题思路 :

考虑答案的形态由两部分组成,一部分是包含 \(x\) 的 \(lis\) ,一部分是不包含 \(x\) 的 \(lis\)

前者显然可以维护左右两个 \(dp\) 值然后主席树数一下点,难度在于后者。

对于第二部分,如果 \(x\) 是之前所有 \(lis\) 共有的点,那么第二部分的答案就是 \(lis-1\) ,否则是 \(lis\)

考虑怎么判断一个点是否是所有 \(lis\) 共有,下面先给出方法:

统计每一个点在 \(lis\) 中出现的位置情况,设 \(l[i]\) 表示从左到右以 \(i\) 结尾的 \(lis\) 长度,\(r[i]\) 表示从右到左以 \(i\) 结尾的 \(lis\) 长度,如果 \(l[i]+r[i]-1=lis\),那么 \(i\) 在 \(lis\) 中的出现位置就是 \(l[i]\),记为 \(pos[i]\)

如果说点 \(x\) 在 \(lis\) 中的出现位置 \(z\) 只有 \(x\) 满足 \(pos[x] =z\) ,那么显然 \(x\) 是不能被替代的,其是所有 \(lis\) 共有的点。不然的话必然存在一种方案不经过 \(x\) 到另外一个满足 \(pos[i] = z\) 的点 \(i\) ,因为 \(x\) 在任何方案下不能存在于两个位置,这样的话 \(lis\) 长度就会更长,有矛盾。

所以只需要统计一下每一个 \(i\) 是不是在所有的 \(lis\) 中出现即可,总复杂度 \(O((n+m)logn)\)

某位神仙表示直接上分治 \(O(nlog^2n)\) 就过了

/*program by mangoyang*/
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 400005;
int h[N], L[N], R[N], g[N], pos[N], tot[N], lis, n, m; struct SegmentTree{
int s[N*25], lc[N*25], rc[N*25], rt[N], size;
inline SegmentTree(){ memset(s, 127, sizeof(s)); }
inline void ins(int &u, int pr, int l, int r, int pos, int x){
u = ++size, lc[u] = lc[pr], rc[u] = rc[pr];
if(l == r) return (void)(s[u] = min(s[u], x));
int mid = l + r >> 1;
if(pos <= mid) ins(lc[u], lc[pr], l, mid, pos, x);
else ins(rc[u], rc[pr], mid + 1, r, pos, x);
s[u] = min(s[lc[u]], s[rc[u]]);
}
inline int query(int u, int l, int r, int x){
if(l == r) return l;
int mid = l + r >> 1;
if(s[rc[u]] < x) return query(rc[u], mid + 1, r, x);
if(s[lc[u]] < x) return query(lc[u], l, mid, x);
return 0;
}
}S1, S2;
int main(){
read(n), read(m);
for(int i = 1; i <= n; i++) read(h[i]);
for(int i = 1; i <= n; i++) g[i] = inf;
for(int i = 1; i <= n; i++){
L[i] = lower_bound(g, g + n, h[i]) - g;
g[L[i]] = min(g[L[i]], h[i]), lis = Max(lis, L[i]);
}
for(int i = 0; i <= n; i++) g[i] = 0; g[0] = -inf;
for(int i = n; i >= 1; i--){
R[i] = lower_bound(g, g + n, -h[i]) - g;
g[R[i]] = min(g[R[i]], -h[i]);
}
for(int i = 1; i <= n; i++)
if(L[i] + R[i] - 1 == lis) pos[i] = L[i], tot[pos[i]]++;
for(int i = 1; i <= n; i++)
S1.ins(S1.rt[i], S1.rt[i-1], 1, n, L[i], h[i]);
for(int i = n; i >= 1; i--)
S2.ins(S2.rt[i], S2.rt[i+1], 1, n, R[i], -h[i]);
for(int i = 1, x, y; i <= m; i++){
read(x), read(y); int res = 0;
if(x > 1) res += S1.query(S1.rt[x-1], 1, n, y);
if(x < n) res += S2.query(S2.rt[x+1], 1, n, -y);
printf("%d\n", max(res + 1, (pos[x] && (tot[pos[x]] == 1)) ? lis - 1 : lis));
}
return 0;
}

Codeforces 650 D. Zip-line的更多相关文章

  1. [codeforces 549]G. Happy Line

    [codeforces 549]G. Happy Line 试题描述 Do you like summer? Residents of Berland do. They especially love ...

  2. codeforces 251A Points on Line(二分or单调队列)

    Description Little Petya likes points a lot. Recently his mom has presented him n points lying on th ...

  3. codeforces 650 C. Watchmen(数学公式)

    C. Watchmen time limit per test 3 seconds memory limit per test 256 megabytes input standard input o ...

  4. codeforces 431 B Shower Line【暴力】

    题意:给出五个人的编号,分别为 1 2 3 4 5,他们在排队, 最开始的时候,1和2可以交谈,3和4可以交谈 然后1走了之后,2和3交谈,4和5可以交谈 2走了之后,3和4可以交谈, 3走了之后,4 ...

  5. 【Codeforces 650 D】Zip-line

    题意:给一个序列以及\(n\)个查询,每一个查询是问(假装)把第\(a_i\)个数改为\(b_i\)之后原序列的最长上升子序列的长度. 思路:线段树优化\(dp\). 肯定离线做啊. 首先我们考虑\( ...

  6. Codeforces 1159F Winding polygonal line(叉积)

    其实这个几何写起来还是比较方便,只用到了叉积.首先我们贪心的考虑一种情况,对于任意给定的LR串,我们起点的选择肯定是在这些点围成的凸包端点上,对于这样的起点来说,他对于L或者R都是有选择的机会,而且一 ...

  7. @codeforces - 594E@ Cutting the Line

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个字符串 s 与正整数 k.现在你需要进行恰好一次操作: ...

  8. 【Codeforces Round 650】Codeforces #334 (Div. 1)

    模拟CF650,ABC三题,RK90 Codeforces 650 A 思路:首先看式子 \(\sqrt{(x_i-x_j)^2+(y_i-y_j)^2}=|x_i-x_j|+|y_i-y_j|\) ...

  9. Codeforces Round #345 (Div. 1) D. Zip-line 上升子序列 离线 离散化 线段树

    D. Zip-line 题目连接: http://www.codeforces.com/contest/650/problem/D Description Vasya has decided to b ...

随机推荐

  1. 网络流入门--最大流算法Dicnic 算法

    感谢WHD的大力支持 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2,3,4},有向管道{A,B,C,D,E},即有向图一张.  ...

  2. 【Linux 命令】fping ping 包间隔时间详解

    服务器间检查会用到fping的命令,期间遇到了一个问题,需要将ping包间的间隔时间设置为100毫秒,查看fping -h看下,找到了-i和-p两个参数: 看到这两个参数,我当时的表情是这样的: 看不 ...

  3. sublime出现卡顿的现象

    这几天,用sublime总是写一个代码就卡顿,卡卡卡,,,,要死的~ 最后,才发现是因为安装了一个插件:GitGutter插件,所以,小伙伴们请跟上我的节奏~~~~~ (1)Ctrl + Shift ...

  4. MSSQL 详解SQL Server连接(内连接、外连接、交叉连接)

    在查询多个表时,我们经常会用“连接查询”.连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志. 什么是连接查询呢? 概念:根据两个表或多个表的列之间的关系,从这些表中查询数据 ...

  5. bzoj 1934最小割

    比较显然的最小割的题,增加节点source,sink,对于所有选1的人我们可以(source,i,1),选0的人我们可以(i,sink,1),然后对于好朋友我们可以连接(i,j,1)(j,i,1),然 ...

  6. 好久没写了,SQLSERVER服务丢失后怎么办

    服务器突然中了病毒,查杀后,结果两个服务也丢了, 从其他机器上COPY了两个EXE过来,编写这两个服务就搞定了,不用重装MSSQL2005了 sc create MSSQLSERVER binpath ...

  7. 残差网络(Residual Network)

    一.背景 1)梯度消失问题 我们发现很深的网络层,由于参数初始化一般更靠近0,这样在训练的过程中更新浅层网络的参数时,很容易随着网络的深入而导致梯度消失,浅层的参数无法更新. 可以看到,假设现在需要更 ...

  8. Nginx实现404页面的几种方法【转】

    一个网站项目,肯定是避免不了404页面的,通常使用Nginx作为Web服务器时,有以下集中配置方式,一起来看看. 第一种:Nginx自己的错误页面 Nginx访问一个静态的html 页面,当这个页面没 ...

  9. Nginx1.8.1 编译扩展https

    nginx无缝编译扩展https 本贴只限用于通过编译安装的nginx,如果用的是yum源安装请卸载后参见 http://www.cnblogs.com/rslai/p/7851220.html 安装 ...

  10. CentOS 7.1使用yum安装MySql5.6.24

    http://www.cnblogs.com/yuanfeiblog/p/5276492.html