题目链接: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的更多相关文章

  1. CF#345 (Div1)

    论蒟蒻如何被cf虐 以下是身败名裂后的题解菌=========== Div1 A.Watchmen 有n个点,每个点有一个坐标.求曼哈顿距离=欧几里得距离的点对数量. 只需要统计x或y一样的点对数量. ...

  2. CF#462 div1 D:A Creative Cutout

    CF#462 div1 D:A Creative Cutout 题目大意: 原网址戳我! 题目大意: 在网格上任选一个点作为圆中心,然后以其为圆心画\(m\)个圆. 其中第\(k\)个圆的半径为\(\ ...

  3. CF #356 div1 A. Bear and Prime 100

    题目链接:http://codeforces.com/contest/679/problem/A CF有史以来第一次出现交互式的题目,大致意思为选择2到100中某一个数字作为隐藏数,你可以询问最多20 ...

  4. 【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 ...

  5. CF 319B Psychos in a Line 【单调队列】

    维护一个单调下降的队列. 对于每一个人,只需要找到在他前面且离他最近的可以杀掉他的人即可. #include <cstdio> #include <vector> #inclu ...

  6. CF#345 div2 A\B\C题

    A题: 贪心水题,注意1,1这组数据,坑了不少人 #include <iostream> #include <cstring> using namespace std; int ...

  7. CF #228 div1 B. Fox and Minimal path

    题目链接:http://codeforces.com/problemset/problem/388/B 大意是用不超过1000个点构造一张边权为1的无向图,使得点1到点2的最短路的个数为给定值k,其中 ...

  8. CF #349 div1 B. World Tour

    题目链接:http://codeforces.com/problemset/problem/666/B 大意是给一张有向图,选取四个点,使得走这四个点,任意两个点之间走最短路,总距离最长. 3000个 ...

  9. CF #335 div1 A. Sorting Railway Cars

    题目链接:http://codeforces.com/contest/605/problem/A 大意是对一个排列进行排序,每一次操作可以将一个数字从原来位置抽出放到开头或结尾,问最少需要操作多少次可 ...

随机推荐

  1. wemall app商城系统Android之支付宝接口RSA函数

    wemall-mobile是基于WeMall的Android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享支付宝接口RSA函数,RSA签名.验签.解密等 ...

  2. iOS程序进入后台,延迟指定时间退出

    程序进入后台,延迟指定时间退出 正常程序退出后,会在几秒内停止工作:要想申请更长的时间,需要用到beginBackgroundTaskWithExpirationHandlerendBackgroun ...

  3. java+++IO流操作

    序:IO流的操作主要分为两种读和写.一方面:我们可以通过不加缓冲类字符流BufferedReader/Writer和字节流BufferedInputStream/OutputStream来进行简单的读 ...

  4. Solr field alias

    Field alias Any field, function, or transformer can be displayed with a different name in the output ...

  5. Ajax写分页查询(实现不刷新页面)

    获取数据库中大量的信息显示在页面上,必然要使用到分页查询: 若不使用Ajax,而是用其他的方法,肯定是要刷新页面的,用户体检很不好, 所以最好使用Ajax的方法写分页查询: 1.先来找一张数据很多的表 ...

  6. SQL语句流程函数

    本人因为今天用到了流程函数,顿时感觉语法生疏啊,为了防止以后忘记,故写此篇!!! 流程函数是MySQL相对常用的一类函数, 用户可以使用这类函数在一个SQL语句中实现条件选择, 这样能够提高效率. 下 ...

  7. 在python&numpy中切片(slice)

     在python&numpy中切片(slice) 上文说到了,词频的统计在数据挖掘中使用的频率很高,而切片的操作同样是如此.在从文本文件或数据库中读取数据后,需要对数据进行预处理的操作.此时就 ...

  8. 【方法】如何限定IP访问Oracle数据库

    [方法]如何限定IP访问Oracle数据库 1.1  BLOG文档结构图 1.2  前言部分 1.2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知 ...

  9. Octave Tutorial(《Machine Learning》)之第三课《数据计算》

    第三课 Culculating Data 数据计算 矩阵计算 1.简单的四则运算 2.相乘除,乘方运算(元素位运算) ".*"为对应元素的相乘计算 "./"为对 ...

  10. 开源的.NET定时任务组件Hangfire解析

    项目慢慢就要开工了,很多园友都在问这个事情,看来大伙对这事很上心啊,事情需要一步步的来,尽量写出一个我们都满意的项目.以前每次在博客前面都会扯淡一下,不过很多人都抱怨这样做不好,加上我这人扯淡起来就停 ...