Description
有一个国家被一条河划分为南北两部分,在南岸和北岸总共有N对城镇,每一城镇在对岸都有唯一的友好城镇。任何两个城镇都没有相同的友好城镇。每一对友好城镇都希望有一条航线来往。于是他们向政府提出了申请。由于河终年有雾。政府决定不允许有任两条航线交叉(如果两条航线交叉,将有很大机会撞船)。
你的任务是写一个程序来帮政府官员决定他们应拨款兴建哪些航线以使得没有出现交叉的航线最多。
Input
第一行一个整数N(1 <= N <= 500000),表示分布在河两岸的城镇对数。
接下来的N行每行有两个由空格分隔的正数C,D ( C、D<=10^9 ),描述每一对友好城镇沿着河岸与西边境线的距离,C表示北岸城镇的距离而D表示南岸城镇的距离。在河的同一边,任何两个城镇的位置都是不同的。
Output
在安全条件下能够开通的最大航线数目。
Sample Input
7
22 4
2 6
10 3
15 12
9 8
17 17
4 2
Sample Output
4
最长不下降序列,n^2算法。
可以考虑nlogn的优秀算法。
我们开一个s[i]表示有i对城市的最小结尾b。
首先,s数组是单调的,如果有s[j]>s[i](1<=j
又因为a是单调的,所以越后面的二分找到>=now.b的位置,即s[i-1]
#include
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
const int N = 5e5+10;
struct City{
int a,b;
}c[N];
int n;
inline bool cmp(const City&A,const City&b){
return A.as[top])s[++top]=c[i].b;
else s[lower_bound(s+1,s+top+1,c[i].b)-s]=c[i].b;
}
for(int i=n;i>=1;--i)if(s[i]){cout<
Description
LIS 问题是最经典的动态规划基础问题之一。如果要求一个满足一定条件的最长上升子序列,你还能解决吗?
给出一个长度为 N 整数序列,请求出它的包含第 K个元素的最长上升子序列。
例如:对于长度为 6的序列<2,7,3,4,8,5>,它的最长上升子序列为<2,3,4,5>,但如果限制一定要包含第 2个元素,那么满足此要求的最长上升子序列就只能是<2,7,8>了。
Input
第一行为两个整数 N,K,如上所述。
接下来是N个整数,描述一个序列。
Output
Sample Input
8 6
65 158 170 299 300 155 207 389
Sample Output
4
Hint
【数据范围】
对于60%的数据,满足0
对于100%的数据,满足0
多了个花样必须包含第k个,我们把它以k为界分成两段,前一段照样,后一段求LIS时,判断一下是否大于k就好了。
#include
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
const int N = 2e5+10;
int n,k,ans,vl[N];
inline void init(){
cin>>n>>k;
Inc(i,1,n)cin>>vl[i];
}
int s1[N],top1;
inline void solv1(){
Inc(i,1,k-1){
if(s1[top1]vl[k])s2[lower_bound(s2+1,s2+top2+1,vl[i])-s2]=vl[i];
}
ans+=top2-(upper_bound(s2+1,s2+top2+1,vl[k])-s2)+1;
}
int main(){
init();
solv1();
solv2();
cout<
ps:LIS nlogn的写法是可以记录方案数的,原理类似吧~当然,权值线段树等各种数据结构也可以优化。