题目链接

题目的意思很简单, 就是给你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-;
const int mod = 1e9+;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
const int maxn = 8e5+;
int sum[maxn<<], 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>>;
if(p<=m)
update(p, val, lson);
else
update(p, val, rson);
sum[rt] = max(sum[rt<<],sum[rt<<|]);
}
int query(int L, int R, int l, int r, int rt) {
if(L>R)
return ;
if(L<=l&&R>=r) {
return sum[rt];
}
int m = l+r>>, ret = ;
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 = ;
cin>>n>>m;
for(int i = ; i<=n; i++) {
scanf("%d", &a[i]);
b[cnt++] = a[i];
}
for(int i = ; 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 = ; i<=n; i++) {
a[i] = lower_bound(b, b+cnt, a[i])-b+;
}
for(int i = ; i<=n; i++) {
dp1[i] = query(, a[i]-, , cnt, )+;
for(int j = ; j<v[i].size(); j++) {
int tmp = v[i][j].fi;
int tmpy = lower_bound(b, b+cnt, v[i][j].se)-b+;
dp3[tmp] = query(, tmpy-, , cnt, )+;
}
update(a[i], dp1[i], , cnt, );
}
mem(sum);
for(int i = n; i>=; i--) {
dp2[i] = query(a[i]+, cnt, , cnt, )+;
for(int j = ; j<v[i].size(); j++) {
int tmp = v[i][j].fi;
int tmpy = lower_bound(b, b+cnt, v[i][j].se)-b+;
dp4[tmp] = query(tmpy+, cnt, , cnt, )+;
}
update(a[i], dp2[i], , cnt, );
}
int maxx = ;
for(int i = ; i<=n; i++) {
maxx = max(dp1[i]+dp2[i]-, maxx); //求原数列lis
}
for(int i = ; i<=n; i++) {
if(dp1[i]+dp2[i]- == maxx) {
num[dp1[i]]++; //如果num[dp1[i]] == 1, 那么它就是关键节点
}
}
for(int i = ; i<m; i++) {
int tmp = maxx;
if(dp1[x[i]]+dp2[x[i]]- == maxx && num[dp1[x[i]]] == ) {
tmp--;
}
tmp = max(tmp, dp3[i]+dp4[i]-);
ans[i] = tmp;
}
for(int i = ; i<m; i++) {
printf("%d\n", ans[i]);
}
return ;
}

codeforces 650D. Zip-line 线段树的更多相关文章

  1. Buses and People CodeForces 160E 三维偏序+线段树

    Buses and People CodeForces 160E 三维偏序+线段树 题意 给定 N 个三元组 (a,b,c),现有 M 个询问,每个询问给定一个三元组 (a',b',c'),求满足 a ...

  2. CodeForces 877E DFS序+线段树

    CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...

  3. [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)

    [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...

  4. [Codeforces 1199D]Welfare State(线段树)

    [Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...

  5. [Codeforces 316E3]Summer Homework(线段树+斐波那契数列)

    [Codeforces 316E3]Summer Homework(线段树+斐波那契数列) 顺便安利一下这个博客,给了我很大启发(https://gaisaiyuno.github.io/) 题面 有 ...

  6. CodeForces 228D. Zigzag(线段树暴力)

    D. Zigzag time limit per test 3 seconds memory limit per test 256 megabytes input standard input out ...

  7. Codeforces 626G Raffles(贪心+线段树)

    G. Raffles time limit per test:5 seconds memory limit per test:256 megabytes input:standard input ou ...

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

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

  9. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  10. Codeforces 482B Interesting Array(线段树)

    题目链接:Codeforces 482B Interesting Array 题目大意:给定一个长度为N的数组,如今有M个限制,每一个限制有l,r,q,表示从a[l]~a[r]取且后的数一定为q,问是 ...

随机推荐

  1. 学习DTD和Schema的几个例子

    可以使用DTD(文档类型定义)来规定xml文档构建模块,可用起对xml文件进行验证.具体用法转:http://www.w3school.com.cn/dtd/dtd_intro.asp.同样也可以用S ...

  2. Quartz 2D 概述

    Quartz 2D是一个二维图形绘制引擎,支持iOS环境和Mac OS X环境.我们可以使用Quartz 2D API来实现许多功能,如基本路径的绘制.透明度.描影.绘制阴影.透明层.颜色管理.反锯齿 ...

  3. OC中对象拷贝概念

    OC中的对象拷贝概念,这个对于面向对象语言中都会有这种的问题,只是不同的语言有不同的解决方式:C++中有拷贝构造函数,Java中需要实现Cloneable接口,在clone方法中进行操作.但是不过OC ...

  4. 超快速使用docker在本地搭建hadoop分布式集群

    超快速使用docker在本地搭建hadoop分布式集群 超快速使用docker在本地搭建hadoop分布式集群 学习hadoop集群环境搭建是hadoop入门的必经之路.搭建分布式集群通常有两个办法: ...

  5. Asp.net MVC学习--默认程序结构、工作流程

    二.MVC 默认程序结构 MVC新建好之后,会对应的出现几个包,分别是:Controller.Model.View --即MVC 其中的默认的Default.aspx文件可以方便url重写,如果不设置 ...

  6. 九度OnlineJudge之1021:统计字符

    题目描述:     统计一个给定字符串中指定的字符出现的次数. 输入:     测试输入包含若干测试用例,每个测试用例包含2行,第1行为一个长度不超过5的字符串,第2行为一个长度不超过80的字符串.注 ...

  7. 如何在XML 加入特殊字符内容 如< >

    XML 文件本身包含了一些预定义的保留字符 如< 标记元素的开始符号等 如果要在属性或者元素的值里面包含类似的这些特殊字符 应该如何处理呢 ? 这时候要用到  <![CDATA[] 这个标 ...

  8. 面向对象程序设计-C++_课时22向上造型

    赋值兼容规则是指在公有派生情况下,一个派生类的对象可以作为基类的对象来使用的情况. 约定类derived是从类base公有派生而来的,则指如下3种情况: (1)派生的对象可以赋给基类的对象.例如: d ...

  9. icon

    <link rel="icon" href="favicon.ico" type="image/x-icon"> <lin ...

  10. Android View动画

    Animation TypeEvaluator View的animate方法 ValueAnimator ObjectAnimator AnimatorSet 使用xml来创建动画 animation ...