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 大意是对一个排列进行排序,每一次操作可以将一个数字从原来位置抽出放到开头或结尾,问最少需要操作多少次可 ...
随机推荐
- DOM基础(一)
在我们刚刚学JavaScript的时候,就应该听说过,JavaScript是由三部分组成的.分别是ECMAScript,DOM和BOM组成的.ECMAScript是JavaScript的核心,它描述了 ...
- WeMall的Android app商城中的wemall doraemon代码
WeMall-Android 包含SMSSDK/WeMall-Client/social_sdk_library_project三个项目以及Api目录下的client.php/update.xml接口 ...
- 2764: [JLOI2011]基因补全
2764: [JLOI2011]基因补全 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 570 Solved: 187[Submit][Status ...
- Broken pipe错误终极解释
叙述 想必或多或少在Java的服务器都会遇到过这种异常,如下图 由于Java偏上层,日常开发接触系统底层的机会偏少,要搞清楚什么原因导致的这种异常,肯定是先要百度google一番. 网络 ...
- android 透明状态栏方法及其适配键盘上推(二)
在上一篇文章中介绍了一种设置透明状态栏及其适配键盘上推得方法.但是上一篇介绍的方法中有个缺点,就是不能消除掉statusbar的阴影.很多手机如(三星,Nexus都带有阴影).即使我用了: <a ...
- Java EE基础之JSP(三)
原来准备简单点,用一篇文章介绍完JSP的,没想到细节很多.这是第三篇也是最后一篇,这三篇文章介绍了基本的JSP知识,很多名词概念和用法,一定要在实践项目中使用之后才会有更加亲切的体会.第三篇 ...
- Ant.SOA微服务框架开源
开源地址:https://github.com/yuzd/AntServiceStack 框架特色0.Service Management(服务治理) 1.CodeGen Contract Fir ...
- 《ECMAScript标准入门》第二版读书笔记
title: <ECMAScript标准入门>第二版 date: 2017-04-10 tags: JavaScript categories: Reading-note 2015年6月, ...
- 华为C8812E 手机logcat不出日志解决方案
最近在弄Android,使用的测试机为华为C8812E,无论如何也打印不出来日志,在网上搜索了一圈,尝试了很久终于解决了,留作备忘. 华为手机logcat不出日志解决方案 进入拨号界面输入:*#*#2 ...
- python 语句:条件、循环、break、continue...
1. 条件语句 执行条件:判断条件"成立时(非零),则执行后面的语句,而执行内容可以多行,以缩进来区分表示同一范围. [Python程序语言指定任何非0和非空(null)值为true,0 或 ...