codeforces 650D. Zip-line 线段树
题目的意思很简单, 就是给你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,问是 ...
随机推荐
- javascript 全选与反选
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> ...
- centos防火墙端口配置
增加防火墙配置,允许8080端口: # vi /etc/sysconfig/iptables 在允许ssh的下面增加一条: -A INPUT -m state --state NEW -m tcp - ...
- iOS坐标转换
// 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 - (CGPoint)convertPoint:(CGPoint)point toView:(UI ...
- php获取文章内容中的全部图片数组
<?php $pattern="/<img.*?src=[\'|\"](.*?(?:[\.gif|\.jpg]))[\'|\"].*?[\/]?>/&q ...
- JVM学习之强引用、弱引用、软引用、虚引用
转自:http://my.oschina.net/ydsakyclguozi/blog/404389 多谢博主分享 1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象 ...
- js闭包陷阱问题
JavaScript是一种非常强大的函数式编程语言,可以动态创建函数对象. 由于JavaScript还支持闭包(Closure),因此,函数可以引用其作用域外的变量,非常强大. 来看看在JavaScr ...
- 常用js表单文本域验证
1.验证是否为正确的邮箱地址 注意:本方法只能验证以@a.b结尾的邮箱地址,对于三级及三级以上的邮箱,比如@iie.ac.cn结尾的会出现错误 function isEmail(o){ var reg ...
- Eclipse 修改字体
- QQ在线咨询状态显示不出来怎么办?http://bizapp.qq.com/webpres.htm
- linux命令学习01-mkdir
1.环境说明 centos6.7,2.6.32-573.el6.x86_64 2.man mkdir NAM mkdir - make directories SYNOPSI ...