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 大意是对一个排列进行排序,每一次操作可以将一个数字从原来位置抽出放到开头或结尾,问最少需要操作多少次可 ...
随机推荐
- MySQL学习分享-->查询-->查询的原理
查询的原理 在一个查询中常包含下述子句: 1.select,2.distinct,3.join,4.on,5.from,6.where,7.having,8.group by,9.order by,1 ...
- 1342: [Baltic2007]Sound静音问题
1342: [Baltic2007]Sound静音问题 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 710 Solved: 307[Submit][ ...
- Java容器源码解析之——ArrayList
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...
- 队列工厂之RabbitMQ
本次和大家分享的是RabbitMQ队列的用法,前一篇文章队列工厂之(MSMQ)中在描述的时候已经搭建了简单工厂,因此本章内容是在其之上扩充的子项不再过多讲解工厂的代码了:RabbitMQ应该是现在互联 ...
- Jmeter 正则提取器
背景: 用户购买商品,为防止CSRF攻击,在购买请求参数中要携带token参数,token的值是随机加密处理的,每次登录值都会刷新 场景: 用户登录站点,访问商品列表,购买商品 脚本设计: 1.登录 ...
- css布局与盒子模型
一. 盒子模型 注: 1.红色为border; 2.背景应用于内容.内边距.边框组成的区域: 3.Width和height指的是内容区域的高度和宽度. 边框属性: 1. padding属性:( ...
- “Dynamic Web Module 3.0 requires Java 1.6 or newer.”错误 (转别人)
eclipse maven 在项目的pom.xml的<build></build>标签中加入: <plugins> <plugin> <group ...
- Java 中的数组
1.声明数组String [] arr;int arr1[];String[] array=new String[5];int score[]=new int[3]; 2.初始化数组://静态初始化i ...
- spdlog源码阅读 (3): log_msg和BasicWriter
4. log_msg和它的打手BasicWriter 在spdlog源码阅读 (2): sinks的创建和使用中,提到log_msg提供了存储日志的功能.那么到底在spdlog中它是怎么 起到这个作用 ...
- Android解析xml文件-采用DOM,PULL,SAX三种方法解析
解析如下xml文件 <?xml version="1.0" encoding="UTF-8"?> <persons> <perso ...