CF #345 Div1 D Zip-line
题目链接:http://codeforces.com/contest/650/problem/D
大意是给一个数组,若干询问,每一次把一个数字改为另一个数字,问当前数组最长上升子序列,询问之间是独立的。
注意到:假设初始数组的LIS长度为len。如果某一个位置的数字属于所有LIS,那么即便这个位置的数字被更改,答案至少是len-1,也有可能会因为变化维持len不变(未必是因为变化介于原来LIS前一个数字和后一个数字之间)。如果某一个位置的数字不是属于所有的LIS(属于某一种或者不属于任何LIS),那么答案至少是len,但也有可能因为变化新答案为len+1。至此,处理出所有位置的数字是否属于所有LIS的情况后,所有询问有了保底的答案。对于这两种情况,可能会产生不保底的情况,则需要对每一个询问查询,左边小于新数字的最大dp值,与右边大于新数字的最大dp值,两者相加再加上1与保底答案取最大值。具体操作,可以按照询问的位置对询问排序,离线处理。
具体写法有两种,一种是树状数组对原有数组数字与询问新数字全部离散化处理,以及基于LIS O(nlog(n))二分解法的写法。判断一个数字是否属于某一个LIS,条件是f[i]+g[i]==len-1? 其中f[i]和g[i]分别是以a[i]为结尾从1到i的LIS长度以及以a[i]为开端从i到n的LIS长度。判断一个数字是否属于所有LIS,则扫描所有属于某一种LIS的数字,统计它们的f值或者g值出现次数,如果某一个f值只出现了1次,则说明拥有这个f值的数字被所有LIS经过。
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <queue>
#include <stack>
#include <map>
#include <set> using namespace std; const int N=1e6+;
int a[N],b[N];
struct Query {
int p,v;
int id;
int ans;
int l,r;
bool operator < (const Query &o) const {
return p<o.p;
}
}query[N]; int t[N];
inline int lowbit(int x) {
return x&(-x);
}
void upd(int x,int v) {
for (;x<N;x+=lowbit(x))
t[x]=max(t[x],v);
}
int ask(int x) {
int ret=;
for (;x;x-=lowbit(x))
ret=max(ret,t[x]);
return ret;
}
int lis(int n,int *f){
memset(t,,sizeof t);
int ret=;
for (int i=;i<n;i++) {
int d=ask(a[i]-);
upd(a[i],d+);
f[i]=d+;
ret=max(ret,d+);
}
return ret;
}
bool flag[N];int cnt[N];
int ret[N];
int f[N],g[N];
int main(){
int n,m;
scanf("%d %d",&n,&m);
for (int i=;i<n;i++) {
scanf("%d",a+i);
b[i]=a[i];
}
int tot=n;
for (int i=;i<m;i++) {
int x,y;
scanf("%d %d",&x,&y);
query[i].p=x-;
query[i].v=y;
query[i].id=i;
b[tot++]=y;
}
sort(b,b+tot);
int k=unique(b,b+tot)-b;
for (int i=;i<n;i++) {
a[i]=lower_bound(b,b+k,a[i])-b+;
}
for (int i=;i<m;i++) {
query[i].v=lower_bound(b,b+k,query[i].v)-b+;
}
int len=lis(n,f);
for (int i=;i<n;i++) {
a[i]=N-a[i];
}
reverse(a,a+n);
lis(n,g);
reverse(g,g+n); reverse(a,a+n);
for (int i=;i<n;i++) {
a[i]=N-a[i];
} memset(cnt,,sizeof cnt);
for (int i=;i<n;i++) {
if (f[i]+g[i]-==len) {
cnt[f[i]]++;
}
}
for (int i=;i<n;i++) {
if (f[i]+g[i]-==len&&cnt[f[i]]==) {
flag[i]=true;
}
} sort(query,query+m);
for (int i=;i<m;i++) {
int p=query[i].p;
if (flag[p])
query[i].ans=len-;
else
query[i].ans=len;
}
int st=;
memset(t,,sizeof t);
for (int i=;i<m;i++) {
int p=query[i].p;
for (;st<p;st++) {
int d=ask(a[st]-);
upd(a[st],d+);
}
int d=ask(query[i].v-);
query[i].l=d;
}
memset(t,,sizeof t);
for (int i=;i<n;i++) {
a[i]=N-a[i];
}
st=n-;
for (int i=m-;i>=;i--) {
int p=query[i].p;
query[i].v=N-query[i].v;
for (;st>p;st--) {
int d=ask(a[st]-);
upd(a[st],d+);
}
int d=ask(query[i].v-);
query[i].r=d;
query[i].ans=max(query[i].ans,query[i].l+query[i].r+);
ret[query[i].id]=query[i].ans;
}
for (int i=;i<m;i++) {
printf("%d\n",ret[i]);
}
return ;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <queue>
#include <stack>
#include <map>
#include <set> using namespace std; const int N=1e6+;
const int INF=0x3f3f3f3f;
int a[N];
struct Query {
int p,v;
int id;
int ans;
int l,r;
bool operator < (const Query &o) const {
return p<o.p;
}
}query[N];
int dp[N];
int f[N],g[N];
int cnt[N];
int lis(int n,int *f){
fill(dp,dp+n,INF);
for (int i=;i<n;i++) {
int pos=lower_bound(dp,dp+n,a[i])-dp;
dp[pos]=a[i];
f[i]=pos+;
}
return lower_bound(dp,dp+n,INF)-dp;
}
bool flag[N];
int ret[N];
int main(){
int n,m;
scanf("%d %d",&n,&m);
for (int i=;i<n;i++) {
scanf("%d",a+i);
}
for (int i=;i<m;i++) {
int x,y;
scanf("%d %d",&x,&y);
query[i].p=x-;
query[i].v=y;
query[i].id=i;
} int len=lis(n,f);
for (int i=;i<n;i++) {
a[i]=-a[i];
}
reverse(a,a+n); lis(n,g);
reverse(g,g+n); for (int i=;i<n;i++) {
a[i]=-a[i];
}
reverse(a,a+n); memset(cnt,,sizeof cnt);
for (int i=;i<n;i++) {
if (f[i]+g[i]-==len) {
cnt[f[i]]++;
}
}
for (int i=;i<n;i++) {
if (f[i]+g[i]-==len&&cnt[f[i]]==) {
flag[i]=true;
}
} sort(query,query+m);
for (int i=;i<m;i++) {
int p=query[i].p;
if (flag[p])
query[i].ans=len-;
else
query[i].ans=len;
} int st=;
fill(dp,dp+n,INF);
for (int i=;i<m;i++) {
int p=query[i].p;
for (;st<p;st++) {
int pos=lower_bound(dp,dp+n,a[st])-dp;
dp[pos]=a[st];
}
int pos=lower_bound(dp,dp+n,query[i].v)-dp;
query[i].l=pos;
} for (int i=;i<n;i++) {
a[i]=-a[i];
}
st=n-;
fill(dp,dp+n,INF);
for (int i=m-;i>=;i--) {
int p=query[i].p;
for (;st>p;st--) {
int pos=lower_bound(dp,dp+n,a[st])-dp;
dp[pos]=a[st];
}
int pos=lower_bound(dp,dp+n,-query[i].v)-dp;
query[i].r=pos;
query[i].ans=max(query[i].ans,query[i].l+query[i].r+);
ret[query[i].id]=query[i].ans;
}
for (int i=;i<m;i++) {
printf("%d\n",ret[i]);
}
return ;
}
CF #345 Div1 D Zip-line的更多相关文章
- CF#345 (Div1)
论蒟蒻如何被cf虐 以下是身败名裂后的题解菌=========== Div1 A.Watchmen 有n个点,每个点有一个坐标.求曼哈顿距离=欧几里得距离的点对数量. 只需要统计x或y一样的点对数量. ...
- CF#462 div1 D:A Creative Cutout
CF#462 div1 D:A Creative Cutout 题目大意: 原网址戳我! 题目大意: 在网格上任选一个点作为圆中心,然后以其为圆心画\(m\)个圆. 其中第\(k\)个圆的半径为\(\ ...
- CF #356 div1 A. Bear and Prime 100
题目链接:http://codeforces.com/contest/679/problem/A CF有史以来第一次出现交互式的题目,大致意思为选择2到100中某一个数字作为隐藏数,你可以询问最多20 ...
- 【Codeforces】#345 Div1
1. Watchmen1.1 题目描述给$n$个点,求曼哈顿距离等于欧式距离的点对数. 1.2 基本思路由$|x_i-x_j|+|y_i-yj| = \sqrt{(x_i-x_j)^2+(y_i-yj ...
- CF 319B Psychos in a Line 【单调队列】
维护一个单调下降的队列. 对于每一个人,只需要找到在他前面且离他最近的可以杀掉他的人即可. #include <cstdio> #include <vector> #inclu ...
- CF#345 div2 A\B\C题
A题: 贪心水题,注意1,1这组数据,坑了不少人 #include <iostream> #include <cstring> using namespace std; int ...
- CF #228 div1 B. Fox and Minimal path
题目链接:http://codeforces.com/problemset/problem/388/B 大意是用不超过1000个点构造一张边权为1的无向图,使得点1到点2的最短路的个数为给定值k,其中 ...
- CF #349 div1 B. World Tour
题目链接:http://codeforces.com/problemset/problem/666/B 大意是给一张有向图,选取四个点,使得走这四个点,任意两个点之间走最短路,总距离最长. 3000个 ...
- CF #335 div1 A. Sorting Railway Cars
题目链接:http://codeforces.com/contest/605/problem/A 大意是对一个排列进行排序,每一次操作可以将一个数字从原来位置抽出放到开头或结尾,问最少需要操作多少次可 ...
随机推荐
- 关于JavaScript简单描述
1.什么是JavaScript? JavaScript 是一种专门用于与网页交互而设计的脚本语言,它有三部分组成,那是哪三部分呢?分别是ECMAScript(提供核心语言功能),DOM(提供访问和操作 ...
- TP框架数据库操作(增删改)
首先选择一张表,对其进行操作: 对数据库操作之前首先要创建模型: $n = M("account"); 数据库添加数据: 1.使用数组: 1.使用数组 $arr = array(& ...
- TypeScript设计模式之中介者、观察者
看看用TypeScript怎样实现常见的设计模式,顺便复习一下. 学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到用哪个模式可以解决,UML忘了可以查,思想 ...
- PowerDesigner建模应用(一)逆向工程,配置数据源并导出PDM文件
物理数据模型(Physical Data Model)PDM,提供了系统初始设计所需要的基础元素,以及相关元素之间的关系:数据库的物理设计阶段必须在此基础上进行详细的后台设计,包括数据库的存储过程.操 ...
- 腾讯云数据库团队:SQL Server 数据加密功能解析
数据加密是数据库被破解.物理介质被盗.备份被窃取的最后一道防线:数据加密,一方面解决数据被窃取安全问题,另一方面有关法律要求强制加密数据:SQL Server 的数据加密相较于其他数据库,功能相对完善 ...
- PMS5003ST+Arduino Nano 串口读取数据
先上代码: 库文件是在guihub上的大神写的https://github.com/jbanaszczyk,我拿来小改下用以支持5003ST #include <Arduino.h> #i ...
- Bug跟踪的流程
本文以翼发云协同项目管理系统为例子来讲解Bug跟踪的流程,它以工作流为中心的集成式Bug跟踪软件,它广泛地应用于研发行业的产品缺陷管理 与跟踪.事务跟踪.问题跟踪.任务跟踪.查询跟踪.需求管理.变更跟 ...
- php文件基本操作与文件管理功能
文件的基本操作 先来看一下PHP文件基础操作,请看强大注释 <body> <?php var_dump(filetype("./img/11.png")); // ...
- Angular 2的12个经典面试问题汇总(文末附带Angular测试)
Angular作为目前最为流行的前端框架,受到了前端开发者的普遍欢迎.不论是初学Angular的新手,还是有一定Angular开发经验的开发者,了解本文中的12个经典面试问题,都将会是一个深入了解和学 ...
- Oracle数据块损坏的恢复实例
测试环境:11.2.0.4 1.构建数据块损坏的测试环境 2.有备份:常规恢复坏块 3.无备份:跳过坏块 1.构建数据块损坏的测试环境 1.1 创建测试表 --Create Table t_test ...