题目的意思很简单, 就是给你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 线段树的更多相关文章
-
Buses and People CodeForces 160E 三维偏序+线段树
Buses and People CodeForces 160E 三维偏序+线段树 题意 给定 N 个三元组 (a,b,c),现有 M 个询问,每个询问给定一个三元组 (a',b',c'),求满足 a ...
-
CodeForces 877E DFS序+线段树
CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...
-
[Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)
[Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...
-
[Codeforces 1199D]Welfare State(线段树)
[Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...
-
[Codeforces 316E3]Summer Homework(线段树+斐波那契数列)
[Codeforces 316E3]Summer Homework(线段树+斐波那契数列) 顺便安利一下这个博客,给了我很大启发(https://gaisaiyuno.github.io/) 题面 有 ...
-
CodeForces 228D. Zigzag(线段树暴力)
D. Zigzag time limit per test 3 seconds memory limit per test 256 megabytes input standard input out ...
-
Codeforces 626G Raffles(贪心+线段树)
G. Raffles time limit per test:5 seconds memory limit per test:256 megabytes input:standard input ou ...
-
Codeforces 833B 题解(DP+线段树)
题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...
-
Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
-
Codeforces 482B Interesting Array(线段树)
题目链接:Codeforces 482B Interesting Array 题目大意:给定一个长度为N的数组,如今有M个限制,每一个限制有l,r,q,表示从a[l]~a[r]取且后的数一定为q,问是 ...
随机推荐
-
[.net 面向对象程序设计进阶] (5) Lamda表达式(一) 创建委托
[.net 面向对象程序设计进阶] (5) Lamda表达式(一) 创建委托 本节导读: 通过学习Lambda表达式,学会创建委托和表达式目录树,深入了解Lambda的特性,让你的代码变的更加清晰. ...
-
使用 DJ Java Decompiler 将整个jar包反编译成源文件
使用 DJ Java Decompiler 将整个jar包反编译成源文件 所使用的软件是 DJ Java Decompiler 3.9. 下面是一个有用的参考文档,说明如何批量编译 http://ww ...
-
ArcSde for Oracle服务注册
1.首先安装ArcSde,安装完成之后在dos命令窗口运行如下命令: sdeservice -o create -d oracle,instance -p sde -i port; 参数说明: ins ...
-
Redis 学习开发笔记
Redis特点: 1.速度快 2.支持丰富的数据类型:字符串.哈希列表.集合 3.操作具有原子性,所有Redis操作都是原子操作 4.多实用工具,可应用如缓存,消息队列,应用程序中任何短期数据,如we ...
-
基于嵌入式操作系统VxWorks的多任务并发程序设计(2) ――任务控制
4 任务与任务状态 VxWorks实时内核Wind提供了基本的多任务环境.对用户而言,宏观上看起来,多个任务同时在执行.而本质而言,在微观上,系统内核中的任务调度器总是在根据特定的调度策略让它们交替运 ...
-
Android O广播接收情况
target-261.卸载和清除收据(这两个在例外广播列表中) 可以收到广播2.应用商店升级app 收不到android.intent.action.PACKAGE_REPLACED广播,应用自身可以 ...
-
SQL Server 只安装客户端的方法
只安装管理工具
-
BootLoader简介(借鉴)
一.BootLoader内容 Bootloader内容包含CPU的初始化.硬件外围接口初始化和内存空间映射表建立.其目的是建立适合操作系统和应用软件运行的系统环境.BootLoader固化在ROM或F ...
-
Android 解决启动页白屏或者黑屏的问题
欢迎页启动的线程由于请求和处理的数据量过大而,导致欢迎页在出现之前界面上会有一个短暂的白色闪屏停留,当然白色闪屏的停留是因为 application 的主题样式android:theme=@style ...
-
vim : Depends: vim-common (= 2:7.4.052-1ubuntu3.1) but 2:7.4.273-2ubuntu4 is to be installed
sudo apt-get purge vim-commonsudo apt-get updatesudo apt-get upgradesudo apt-get install vim