codevs1906 最长递增子序列问题
给定正整数序列x1,..... , xn 。
(1)计算其最长递增子序列的长度s。
(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长
度为s的递增子序列。
第1 行有1个正整数n,表示给定序列的长度。接
下来的1 行有n个正整数x1.....xn 。
第1 行是最长递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。
4
3 6 2 5
2
2
3
不得不吐槽codevs上面网络流24题好多数据都是很蛋疼的要输出方案又不给spj……鬼知道你数据是用哪种方案啊
啊这题还算正常
第一问LIS随便求
第二问拆点完S向所有x1连流量1费用0的边,所有x2向T连流量1费用0的边,所有x1向x2连流量1费用1的边。因为要表示有没有取这个点
对于所有a[i]<a[j]且i<j的,i2向j1连流量1费用0的边
然后跑最大费用。每次增广搞完如果答案是第一问的最长长度,那么ans++。
第三问就是第二问的建图与1和n有关的边的流量全改inf就对了
#include<cstdio>
#include<iostream>
#include<cstring>
#define LL long long
#define inf 0x3ffffff
#define S 0
#define T 1001
using namespace std;
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,ans,flow,cnt,tot;
int a[510];
int mn[510];
struct edge{int from,to,next,v,c;}e[500010];
int head[1010],dis[1010],q[1010],from[1010];
bool mrk[1010];
inline void ins(int u,int v,int w,int c)
{
e[++cnt].to=v;
e[cnt].v=w;
e[cnt].c=c;
e[cnt].from=u;
e[cnt].next=head[u];
head[u]=cnt;
}
inline void insert(int u,int v,int w,int c)
{
ins(u,v,w,c);
ins(v,u,0,-c);
}
inline int bsearch(int x)
{
int l=1,r=ans,s=0;
while(l<=r)
{
int mid=(l+r)>>1l;
if (mn[mid]<=x){s=mid;l=mid+1;}
else r=mid-1;
}
return s;
}
inline bool spfa()
{
for (int i=1;i<=T;i++)dis[i]=inf;
memset(mrk,0,sizeof(mrk));
int t=0,w=1;
dis[S]=0;q[0]=S;mrk[S]=1;
while (t!=w)
{
int now=q[t++];if (t==1005)t=0;
for (int i=head[now];i;i=e[i].next)
if (e[i].v&&dis[now]+e[i].c<dis[e[i].to])
{
dis[e[i].to]=dis[now]+e[i].c;
from[e[i].to]=i;
if (!mrk[e[i].to])
{
mrk[e[i].to]=1;
q[w++]=e[i].to;
if (w==1005)w=0;
}
}
mrk[now]=0;
}
if (dis[T]==inf)return 0;
return 1;
}
inline void mcf()
{
int x=inf;flow=0;
for (int i=from[T];i;i=from[e[i].from])
x=min(x,e[i].v);
for (int i=from[T];i;i=from[e[i].from])
{
e[i].v-=x;
e[i^1].v+=x;
flow+=x*e[i].c;
}
if (flow==-ans)tot++;
}
int main()
{
n=read();
for (int i=1;i<=n;i++)a[i]=read();
ans=1;mn[1]=a[1];
for (int i=2;i<=n;i++)
{
int fnd=bsearch(a[i]);
if (fnd==ans)mn[++ans]=a[i];
else mn[fnd+1]=a[i];
}
printf("%d\n",ans);
cnt=1;
for(int i=1;i<=n;i++)
{
insert(S,i,1,0);
insert(i+n,T,1,0);
insert(i,i+n,1,-1);
}
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
if (a[i]<=a[j])insert(i+n,j,1,0);
while (spfa())mcf();
printf("%d\n",tot);
memset(head,0,sizeof(head));
cnt=1;tot=0;
insert(S,1,inf,0);insert(S,n,inf,0);
insert(1+n,T,inf,0);insert(2*n,T,inf,0);
insert(1,1+n,inf,-1);insert(n,2*n,inf,-1);
for(int i=1;i<=n;i++)
{
insert(S,i,1,0);
insert(i+n,T,1,0);
insert(i,i+n,1,-1);
}
for (int i=1;i<n;i++)
for (int j=i+1;j<=n;j++)
if (a[i]<=a[j])
if (i!=1&&j!=n)insert(i+n,j,1,0);
else insert(i+n,j,inf,0);
while (spfa())mcf();
printf("%d\n",tot);
}
codevs1906 最长递增子序列问题的更多相关文章
- (转载)最长递增子序列 O(NlogN)算法
原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则 ...
- 最长公共子序列(LCS)和最长递增子序列(LIS)的求解
一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...
- 最长递增子序列 O(NlogN)算法
转自:点击打开链接 最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS. 排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了. 假设存在一个 ...
- 51nod 1134 最长递增子序列
题目链接:51nod 1134 最长递增子序列 #include<cstdio> #include<cstring> #include<algorithm> usi ...
- 动态规划 - 最长递增子序列(LIS)
最长递增子序列是动态规划中经典的问题,详细如下: 在一个已知的序列{a1,a2,...,an}中,取出若干数组组成新的序列{ai1,ai2,...,aim},其中下标i1,i2,...,im保持递增, ...
- 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹
一, 最长递增子序列问题的描述 设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1< ...
- 2.16 最长递增子序列 LIS
[本文链接] http://www.cnblogs.com/hellogiser/p/dp-of-LIS.html [分析] 思路一:设序列为A,对序列进行排序后得到B,那么A的最长递增子序列LIS就 ...
- 【动态规划】拦截导弹_dilworth定理_最长递增子序列
问题 K: [动态规划]拦截导弹 时间限制: 1 Sec 内存限制: 256 MB提交: 39 解决: 10[提交][状态][讨论版] 题目描述 张琪曼:“老师,修罗场是什么?” 墨老师:“修罗是 ...
- COGS731 [网络流24题] 最长递增子序列(最大流)
给定正整数序列x1,..., xn (n<=500).(1)计算其最长递增子序列的长度s.(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列.(3)如果允许在取出的序列中多次使用x1和 ...
随机推荐
- android中画文字的换行 办法(对于遇到canvas.drawText(String s )无法实现换行问题的解决)
在使用canvas.drawText()绘制文字的时候,发现,如果需要绘制的文字较长,需要换行,通过在文字中加上“\n"或者”\r\n"都无法实现换行,如果非要使用canvas.d ...
- USACO lamps
IOI 98称号.然后,它似乎没有很困难.即使我能做到这一点微弱的残留物.所有的button按两次不按,高达因此实际上总的等效按4二级,首先C往下<=4,则搜索将能直接照射,总共只有16状态(事 ...
- 表达式求值 (栈) 用C++实现
#include <cstdio> #include <cstdlib> #include <cmath> #include <stack> #incl ...
- Java基础知识强化之集合框架笔记01:集合的由来与数组的区别
1. 集合的由来: 我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储.而要想存储多个对象,就不能是一个基本的变量,而应该 ...
- Java基础知识强化86:BigInteger类之BigInteger概述和构造方法
1. BigInteger类概述 可以让超过Integer范围内的数据进行运算 2. 构造方法: public BigInteger(String val) 3. 代码示例: package cn ...
- Entity Framework 重写OnModelCreating,控制生成表名的单复数
重写OnModelCreating,控制生成表名的单复数 public class MYDbContext : DbContext { public DbSet<User> Users { ...
- How to Build CyanogenMod for One X (codename: endeavoru)
来源:http://wiki.cyanogenmod.org/w/Build_for_endeavoru#What_you.E2.80.99ll_need How to Build CyanogenM ...
- spring 配置触发器 (类似于定时任务)
为什么会看这个? 发现项目中有的service中的方法没有地方调用.经查,发现在web.xml中加载的spring的配置文件中配置了这个方法, 经查这种方式是触发器,会定时执行,只需要配置一下.可以设 ...
- 接入淘宝SDK(OneSDK)和支付宝SDK(AlipaySDK)出现 duplicate symbols for architecture i386
起初我在我的项目中先接入了AlipaySDK,没有出现什么问题,之后想要接入淘宝SDK之后,就出现了duplicate symbols for architecture i386的错误 经过一段时间排 ...
- Ubuntu最小化桌面快捷键Super+D不生效解决
之前用的Debian,最近研发老大让统一使用Ubuntu来开发,安装了Ubuntu 15.10之后,设置了最小化桌面的快捷键为Super+D(在Systm Settings/系统设置—>Keyb ...