题目链接

题目的意思很简单, 就是给你n个数, m个询问, 每次询问修改某一个位置的值, 然后问你修改完之后数列的lis是多少。 询问独立。

对于原数列, 我们将它离散化, 令dp1[i]为以i为结尾位置的最长上升子序列的长度, dp[2]为以i结尾的从后往前的最长下降子序列的长度。

原数列的lis显然为max(dp1[i]+dp2[i]-1)。

然后我们求出哪些位置是关键位置, 所谓关键位置, 就是说如果把这个位置的值改变, 那么lis的值也许就会减1。  求关键位置的方法看代码。

然后对于每个询问, 令x[i]为位置, y[i]为修改后并离散化的值,我们令dp3[i]表示将x[i]位置修改为y[i]之后, 以x[i]结尾的最长上升子序列的长度, dp4[i]为最长下降的长度。

那么对于每次询问, 如果x[i]是关键节点, ans[i] = max(lis-1, dp3[i]+dp4[i]-1), 否则的话, ans[i] = max(lis, dp3[i]+dp4[i]-1)。

具体的可以看代码。

还有一点要注意的是数组不能开成4e5, 要开成8e5。

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
const int maxn = 8e5+5;
int sum[maxn<<2], num[maxn], dp1[maxn], dp2[maxn], dp3[maxn], dp4[maxn], a[maxn], b[maxn];
int x[maxn], y[maxn], ans[maxn];
vector <pll> v[maxn];
void update(int p, int val, int l, int r, int rt) {if(l == r) {sum[rt] = max(sum[rt], val);return ;}int m = l+r>>1;if(p<=m)update(p, val, lson);elseupdate(p, val, rson);sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
}
int query(int L, int R, int l, int r, int rt) {if(L>R)return 0;if(L<=l&&R>=r) {return sum[rt];}int m = l+r>>1, ret = 0;if(L<=m)ret = query(L, R, lson);if(R>m)ret = max(ret, query(L, R, rson));return ret;
}
int main()
{int n, m, cnt = 0;cin>>n>>m;for(int i = 1; i<=n; i++) {scanf("%d", &a[i]);b[cnt++] = a[i];}for(int i = 0; i<m; i++) {scanf("%d%d", &x[i], &y[i]);b[cnt++] = y[i];v[x[i]].pb(mk(i, y[i]));}sort(b, b+cnt);cnt = unique(b, b+cnt)-b;for(int i = 1; i<=n; i++) {a[i] = lower_bound(b, b+cnt, a[i])-b+1;}for(int i = 1; i<=n; i++) {dp1[i] = query(1, a[i]-1, 1, cnt, 1)+1;for(int j = 0; j<v[i].size(); j++) {int tmp = v[i][j].fi;int tmpy = lower_bound(b, b+cnt, v[i][j].se)-b+1;dp3[tmp] = query(1, tmpy-1, 1, cnt, 1)+1;}update(a[i], dp1[i], 1, cnt, 1);}mem(sum);for(int i = n; i>=1; i--) {dp2[i] = query(a[i]+1, cnt, 1, cnt, 1)+1;for(int j = 0; j<v[i].size(); j++) {int tmp = v[i][j].fi;int tmpy = lower_bound(b, b+cnt, v[i][j].se)-b+1;dp4[tmp] = query(tmpy+1, cnt, 1, cnt, 1)+1;}update(a[i], dp2[i], 1, cnt, 1);}int maxx = 0;for(int i = 1; i<=n; i++) {maxx = max(dp1[i]+dp2[i]-1, maxx);      //求原数列lis
    }for(int i = 1; i<=n; i++) {if(dp1[i]+dp2[i]-1 == maxx) {num[dp1[i]]++;              //如果num[dp1[i]] == 1, 那么它就是关键节点
        }}for(int i = 0; i<m; i++) {int tmp = maxx;if(dp1[x[i]]+dp2[x[i]]-1 == maxx && num[dp1[x[i]]] == 1) {tmp--;}tmp = max(tmp, dp3[i]+dp4[i]-1);ans[i] = tmp;}for(int i = 0; i<m; i++) {printf("%d\n", ans[i]);}return 0;
}

转载于:https://www.cnblogs.com/yohaha/p/5256797.html

codeforces 650D. Zip-line 线段树相关推荐

  1. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  2. Codeforces 997E Good Subsegments (线段树)

    题目链接 https://codeforces.com/contest/997/problem/E 题解 经典题,鸽了 159 天终于看明白题解了.. 考虑一个区间是连续的等价于这个区间内的 \((\ ...

  3. CodeForces - 1539F Strange Array(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,规定位置 iii 的贡献是:设 x=a[i]x=a[i]x=a[i],选择一个包含 iii 的区间 [l,r][l,r][l,r],将其中 ...

  4. CodeForces - 1430E String Reversal(线段树+模拟)

    题目链接:点击查看 题目大意:给出一个字符串 sss ,令其反转的串为 ttt ,每次操作可以将 ttt 中的两个相邻位置的字符交换,问最少需要进行多少次操作才能使得 ttt 变成 sss 题目分析: ...

  5. 【codeforces 12D】【线段树】【降维】【离散化】【三元组比较大小】

    [题意] 给出n个女士的三位属性xi,yi,zi(注意此处是一行x给完再给y再给z).若存在xi>xj && yi > yj  && zi>zj ,那 ...

  6. Codeforces 1108 E2(线段树+思维)

    传送们 题意: 给你一个长度为nnn的数列bbb.以及mmm个区间. 你可以选取111个或多个这样的区间aia_iai​,使得令区间aia_iai​所对应的所有值bib_ibi​都减111.你最终要使 ...

  7. CodeForces - 817F MEX Queries(线段树lazy序)

    题目链接:点击查看 题目大意:初始时有一个空的集合,需要执行 n 次操作: 1 l r:将区间 [ l , r ] 内未出现的数加入到集合中 2 l r:将区间 [ l , r ] 内出现的数字全部删 ...

  8. CodeForces - 1454F Array Partition(线段树+二分)

    题目链接:点击查看 题目大意:给出一个长度为 n 的序列,现在要求求出任意一组 x , y , z,满足下列条件: x + y + z = n max( 1 , x ) = min( x + 1 , ...

  9. CodeForces - 1440E Greedy Shopping(线段树)

    题目链接:点击查看 题目大意:给出一个非严格递减的子序列,需要完成 m 次操作,分为下列两种类型: 1 x y:将区间 [ 1 , x ] 中的数进行 a[ i ] = max( a[ i ] , y ...

  10. CodeForces - 1418G Three Occurrences(线段树-标记永久化)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a ,现在规定 a 中的一段区间 [ l , r ],如果其中每个数字要么出现 0 次要么出现恰好 3 次,就规定这是个好区间,问共有多少个好 ...

最新文章

  1. 用asp.net实现的把本文推荐给好友功能
  2. push与presentModal的 用法详解(转)
  3. julia 调用python库_Julia调用Python实现超像素分割SLIC算法
  4. Mysql京东的一道面试题目 比较综合
  5. Android官方开发文档Training系列课程中文版:电池续航时间优化之检查、检测网络连接状态...
  6. maven 插件使用之:打包jar到lib
  7. 设计模式—建造者模式(思维导图)
  8. 消息中间件解决方案-JMS-ActiveMQ
  9. HP的.NET职位面试题
  10. XML文件怎么转换成Excel表格文件
  11. java基础习题_Java基础知识练习题及答案
  12. Hi3559a移植Opencv3.0
  13. BeetlSql中的Mapper
  14. 关于计算机固态硬盘正确的是,如何对固态硬盘进行初始化?选择合适的格式及分区结构很重要...
  15. html图片自动适应屏幕代码,css让图片宽度自适应屏幕的例子
  16. js点击使内容变成可编辑状态
  17. m3u8 视频提取工具(下载web中的ts文件)
  18. 一只猴子和那些超神的脚本......
  19. okcoin 爱沙尼亚_我如何成为爱沙尼亚的电子居民
  20. 安卓基于Frida HOOK传感器 实现虚拟运动跑步

热门文章

  1. NYOJ 45 棋盘覆盖
  2. 如何查看java对象的大小
  3. Windows下oracle RMAN备份脚本
  4. Android外设存储设备的访问及测试
  5. APP时代,市场选择是个技术活
  6. FPGA跨时钟域处理的三大方法
  7. 数字信号处理中的自相关和互相关计算和物理意义(一)
  8. Windows中文件夹属性加密的作用?
  9. Linux学习笔记-题记
  10. 区块链应用 | 用区块链颠覆视频直播,与视频卡顿、缓冲说再见!