[CTSC2017]最长上升自序列(伪题解)(Dilworth's theorem+网络流)
部分分做法很多,但每想出来一个也就多5~10分。正解还不会,下面是各种部分分做法:
Subtask 1:k=1
LCS长度最长为1,也就是说不存在j>i和a[j]>a[i]同时成立。显然就是一个LDS,树状数组直接求即可。
Subtask 2:k=2
最多两个,也就是可以由两个LCS拼起来,f[i][j]表示第一个LCS以i结尾,第二个以j结尾的方案数,转移显然。
Subtask 3:k=2
树状数组优化DP,复杂度由$O(n^3)$降为$O(n^2 \log n)$
Subtask 4,5:B<=8
DP套DP:https://www.cnblogs.com/clnchanpin/p/7357564.html
一般与“子序列”同时出现,如最长上升自序列,最长公共自序列等。
Subtask 6,7:
一个显然的定理:一个序列的LCS最大为k意味着这个序列最少可以由k个不相交的LDS组成。
考虑网络流,下面(a,b)表示容量为a,费用为b的边。
拆点,in[x]向out[x]连(1,-1)的边,每次和下一个小于这个数的位置连(1,0)的边,增设源汇,最多增广k次即可。
$O(Kn^3)$
Subtask 8,9:
上面的方法点数为$n$,边数为$n^2$,启发我们用线段树优化建图。
这里用树状数组就行了。
点数$n\log n$,边数$n\log n$。
$O(K(n\log n)^2)$
Subtask 10,11,12:
Johnson多源最短路算法:
传统的Floyd是$O(n^3)$的,已经很优秀了。但是如果我们对每个点跑一次Dijkstra,可以得到$O(n^2\log m)$这个更好的复杂度。
但是Dijkstra不能跑有负权边的情况。
考虑增设超级源S并向每个点连长度为0的边,然后跑单源最短路,接着将每条边(u,v,w)改成(u,v,w+(dis[u]-dis[v])),其中dis[u]表示S到u的最短路。
这样跑Dijkstra就是正确的了,转移的时候记录pre方便最后求出最短路长度。
不了解如何运用到这道题上。
优化:可以直接用数组代替堆降低复杂度。
Subtask 13~20:
完全不理解的杨氏矩阵理论。
不断分析将复杂度依次降为:$O(n^2\log n+Q\log n)$,$O(n\sqrt{n}\log n)$,$O(n\sqrt{n\log n})$。
附:树状数组+网络流代码(15pts)
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=;
int x,y,fir[N],pre[N],a[N],b[N],inq[N],dis[N],n,m,cnt=;
int in[N],out[N],ans[N],BIT[N],S,T,cost,lim,obt,tot; struct edge{
int to,nxt,f,c;
edge () {}
edge (int x,int y,int z,int l){ to=y; nxt=fir[x]; f=z; c=l; fir[x]=cnt; }
}e[*N]; void add(int x,int y,int z,int l){ e[++cnt]=edge(x,y,z,l); e[++cnt]=edge(y,x,,-l); } bool spfa(){
int i,x; queue<int> q;
for(i=;i<=T;i++) dis[i]=;
dis[S]=; q.push(S);
while(!q.empty()){
x=q.front(); q.pop();
for(i=fir[x];i;i=e[i].nxt)
if(e[i].f&&dis[e[i].to]>dis[x]+e[i].c){
dis[e[i].to]=dis[x]+e[i].c; pre[e[i].to]=i;
if(!inq[e[i].to]) q.push(e[i].to),inq[e[i].to]=;
}
inq[x]=;
}
return dis[T]!=;
} int aug(){
int x,flow=1e9;
for(x=T;x!=S;x=e[pre[x]^].to) flow=min(flow,e[pre[x]].f);
for(x=T;x!=S;x=e[pre[x]^].to)
cost+=e[pre[x]].c*flow,e[pre[x]].f-=flow,e[pre[x]^].f+=flow;
return flow;
} int dinic(){ int res=; while(spfa()) res+=aug(); return res; } void modify(int p,int x){
for(;x<=obt;x+=x&-x){
tot++;
if(BIT[x]) add(tot,BIT[x],n,);
add(tot,p,,); BIT[x]=tot;
}
} void ask(int p,int x){ for (;x;x-=x&-x) if (BIT[x]) add(p,BIT[x],,); } int main(){
freopen("lis.in","r",stdin);
freopen("lis.out","w",stdout);
scanf("%d%d",&n,&m);
if (n>) { rep(i,,m) printf("0\n"); return ; }
rep(i,,n) scanf("%d",&a[i]),b[i]=a[i];
sort(b+,b+n+); obt=unique(b+,b+n+)-b-;
rep(i,,n) a[i]=lower_bound(b+,b+obt+,a[i])-b;
rep(i,,n) in[i]=i,out[i]=i+n,add(in[i],out[i],,-);
tot=*n;
for (int i=n;i;i--) ask(out[i],a[i]),modify(in[i],a[i]);
S=tot+; T=S+;
rep(i,,n) add(S,in[i],,),add(out[i],T,,);
cost=lim=;
while(spfa()) aug(),ans[++lim]=-cost;
while(m--) scanf("%d%d",&x,&y),printf("%d\n",ans[min(y,lim)]);
return ;
}
[CTSC2017]最长上升自序列(伪题解)(Dilworth's theorem+网络流)的更多相关文章
- 算法复习——求最长不下降序列长度(dp算法)
题目: 题目背景 161114-练习-DAY1-AHSDFZ T2 题目描述 有 N 辆列车,标记为 1,2,3,…,N.它们按照一定的次序进站,站台共有 K 个轨道,轨道遵从先进先出的原则.列车进入 ...
- JDOJ 1929: 求最长不下降序列长度
JDOJ 1929: 求最长不下降序列长度 JDOJ传送门 Description 设有一个正整数的序列:b1,b2,-,bn,对于下标i1<i2<-<im,若有bi1≤bi2≤-≤ ...
- [BZOJ1852] [MexicoOI06]最长不下降序列
[BZOJ1852] [MexicoOI06]最长不下降序列 额我也不知道是不是水过去的...和网上的另一篇题解对拍过了,但是拍不出来... 经过和神仙的讨论基本可以确定是对的了 考虑如下贪心 (我将 ...
- LeetCode 674. Longest Continuous Increasing Subsequence (最长连续递增序列)
Given an unsorted array of integers, find the length of longest continuous increasing subsequence. E ...
- [LeetCode] Longest Continuous Increasing Subsequence 最长连续递增序列
Given an unsorted array of integers, find the length of longest continuous increasing subsequence. E ...
- [Swift]LeetCode674. 最长连续递增序列 | Longest Continuous Increasing Subsequence
Given an unsorted array of integers, find the length of longest continuous increasing subsequence (s ...
- 问题 B: 【例9.3】求最长不下降序列(基础dp)
问题 B: [例9.3]求最长不下降序列 时间限制: 1 Sec 内存限制: 128 MB提交: 318 解决: 118[提交][状态][讨论版][命题人:quanxing] 题目描述 设有由n( ...
- leecode 978. Longest Turbulent Subarray(最长连续波动序列,DP or 滚动数组)
传送门:点我 978. Longest Turbulent Subarray A subarray A[i], A[i+1], ..., A[j] of A is said to be turbule ...
- 九度oj题目1342:寻找最长合法括号序列II
题目1342:寻找最长合法括号序列II(25分) 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:886 解决:361 题目描述: 假如给你一个由’(‘和’)’组成的一个随机的括号序列,当然 ...
随机推荐
- 【NOIP 模拟赛】Evensgn 剪树枝 树形dp
由于树规做的少所以即使我考试想出来正确的状态也不会转移. 一般dp的转移不那么繁杂(除了插头.....),即使多那也是清晰明了的,而且按照树规的一般思路,我们是从下到上的,所以我们要尽量简洁地从儿子那 ...
- 兔子与兔子 [Hash]
兔子与兔子 描述 很久很久以前,森林里住着一群兔子.有一天,兔子们想要研究自己的 DNA 序列.我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母) ...
- APP兼容性测试
一.APP兼容性范围以及问题 1.硬件 各个硬件结构 2.软硬件之间 硬件dll库(C++) 软硬件之间的通信,各个厂商提供的ROM 3.软件 浏览器.操作系统.数据库.手机.功能兼容性(功能修改,二 ...
- 转:Spring AOP详解
转:Spring AOP详解 一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址: ...
- c#之字符串函数
1.常用的字符串函数 Compare 比较字符串的内容,考虑文化背景(场所),确定某些字符是否相等 int Compare(string str1,string str2) int Compare(s ...
- Nios II 中的缓存和内存数据的读写
nios 使用地址中31bit来表示访问是否bypass cache.如果bit 31=0 表示不bypass cache,即使用cache里的数据:如果bit 31=1表示bypass cache, ...
- 【Foreign】划分序列 [线段树][DP]
划分序列 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 9 4 ...
- bzoj1855: [Scoi2010]股票交易 单调队列优化dp ||HDU 3401
这道题就是典型的单调队列优化dp了 很明显状态转移的方式有三种 1.前一天不买不卖: dp[i][j]=max(dp[i-1][j],dp[i][j]) 2.前i-W-1天买进一些股: dp[i][j ...
- mysqli_insert_id
mysqli_insert_id($mysqli),这个函数一开始我用的时候老是返回0,疯掉了,百度了n次,问了n个人,搞了几天,就是解决不了,最后我把他换成面对对象编程,终于成功了,开心,也许这就是 ...
- 会话Cookie
Cookie分为会话Cookie和本地Cookie两种 之前一直理解的是会话Cookie不在本地文件存储,只存储于内存,而本地Cookie因为设置了expire过期时间需要在本地存储 下面是白帽子讲W ...