ZJNU 1217 - 航线问题——高级

将所有航线的其中一边排序后,另一边进行类dp

定义一个数组c,c[i]表示在所有能够开通i条航线的组合中,位置序号最大的那条航线的序号的最小值

比如下面一个样例

1 3

2 4

3 1

4 2

此时对于航线左边的位置序号已经是排好序的了

那么只需要考虑右边的情况

在所有只开通1条航道的组合中

右侧出现的结果可能是{1},{2},{3},{4}

所以c[1]=1

在所有只开通2条航道的组合中

右侧出现的结果可能是{3,4},{1,2}

这里有两个组合,每个组合位置序号最大的元素分别是4和2,取小

得到c[2]=2

同时我们可以发现c数组是严格递增的

那么定义完了c数组,说下它有什么用

因为航线左端排好序,每次考虑的值都是右端序号

重新举个例子

1 4

2 5

3 1

4 2

5 3

只拿右端序列,得到dp对象为4 5 1 2 3

考虑4,得到c[1]=4,答案更新为1

考虑5,因为5>4,且左侧序号递增,所以可以得到这条航线与终点为4的航线不重叠,可以组合,所以c[2]=5,答案更新为2

考虑1,因为c数组内没有元素比1小,所以更新c[1]=1,答案不变,为2

考虑2,得到c[1]<2,所以可以和此时c[1]指代的航线组合,更新c[2]=2,答案不变,为2

考虑3,得到c[2]<3,所以可以和此时c[2]指代的2条航线组合,c[3]=3,答案更新为3

首先,答案就是能够组合在一起的最大数量,即c数组最大的下标

那么为什么可以这样更新呢?

从形式上看,更新了数组之后相当于破坏了前面的航线的结论(看上去会让前面的航线交叉)

实际上,因为每考虑到一个点的时候,可以视为前面的点能组合的都已经组合完毕

更新c数组的元素,是为了贪心让之后的点加进来后对答案贡献更大,让其后的点能有更优的组合

对于代码实现,取用lower_bound函数或者手动模拟二分查找(已知现有c数组是有序的)

 1 /*
 2 Written By StelaYuri
 3 */
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cstring>
 7 #define INF 0x3f3f3f3f
 8 using namespace std;
 9 const int m=100010;
10 struct line{
11     int a,b;
12     bool operator < (const line& x) const{
13         return a<x.a;
14     }
15 }r[m];
16 int c[m];
17 int main(){
18     ios::sync_with_stdio(0);
19     cin.tie(0);cout.tie(0);
20     int T,n,i,p,ans;
21     cin>>T;
22     while(T--){
23         cin>>n;
24         for(i=1;i<=n;i++)
25             cin>>r[i].a>>r[i].b;
26         sort(r+1,r+1+n);
27         memset(c,INF,sizeof c);
28         ans=0;
29         for(i=1;i<=n;i++){
30             p=lower_bound(c+1,c+1+ans,r[i].b)-c;
31             ans=max(ans,p);
32             c[p]=r[i].b;
33         }
34         cout<<ans<<endl;
35     }
36
37     return 0;
38 }

原文地址:https://www.cnblogs.com/stelayuri/p/12233617.html

时间: 2024-10-11 18:42:33

ZJNU 1217 - 航线问题——高级的相关文章

ZJNU 1205 - 侦探推理——高级

双层枚举嫌疑犯与当日是星期几,统计真话与假话是否满足题意 注意 fake<=N&&fake+neutral>=N 即假话数量不大于N,假话加上没用的废话数量不小于N (注意OJ上的数据存在问题:冒号后跟一个空格,CHARLES的话最后的句号‘.’应为半角,非全角) 1 /* 2 Written By StelaYuri 3 */ 4 #include<bits/stdc++.h> 5 using namespace std; 6 typedef pair<in

ZJNU 1223 - 素数距离——高级

因为最大可以达到int极限 明显直接筛选不可能完成 所以从其因子入手 因为任何不是素数的数都有除了1与其自身之外的因子 因此,我们筛出2^(31/2)≍46350之内的所有素数,以其作为因子再将题目给定区间内的所有不是素数的数标记排除 然后将素数存放在prnum这个vector集合中便于调用 在排除阶段,可以用 l=((L+prnum[i]-1)/prnum[i])*prnum[i] 计算出区间内的第一个是prnum[i]的倍数的数 注意,如果计算出来的使其本身,取倍数 再用 r=R/prnum

hdu 3047 Zjnu Stadium 并查集高级应用

Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1631    Accepted Submission(s): 616 Problem Description In 12th Zhejiang College Students Games 2007, there was a new stadium built

zjnu(1183)——括号序列【基础算法?动态规划】——高级

首先,我只想声明一点,这道题有毒...我用char读入就错了,然而换成string读入就对了或者可以把定义char的数组开的大一点,原先1A的一题硬是纠结了老半天. 传送门:zjnu 题意: 就是对于一个组成的序列,添加尽量少的括号得到一个规则序列,并且输出这个序列的长度. 不过我学到了两种定义dp状态的方法: 1)定义dp[i][j]为i~j中需要添加的最少的括号数.这里我们记录s为一段字符的开始位置,e为一段字符的结束位置. ①当(a[s]=='('&&a[e]==')')||(a[s

ZJNU 1196 - 三阶魔方【模拟题】——高级

大模拟,空想很容易把面和面之间的关系搞混 所以这时候需要自己找一个正方体(实在不行长方体代替)跟着图把每个面正方向标出来 然后模拟6种操作分别会对哪些块进行操作 对于储存数据的想法是,对输入输出进行分块,以c[i][j]表示是第i个面的第j块 具体参照下文输入输出内的 for(i=0;i<3;i++) for(j=0;j<18;j++){ scanf("%s",cd); c[j/3][j%3+i*3]=cd[0]; } 与 for(i=0;i<3;i++) for(j

ZJNU 1213 - 取水——高级

某个村庄i可以打一口井取水花费费用Wi,也可以与有水的村庄连接取水 又因为不可能没有一个村庄不打井(即至少有一个村庄打井,其余村庄连向它) 实际上就可以理解为,将水井看作第N+1个村庄,需要有村庄与这个N+1村庄相连,才能保证所有村庄有水 而村庄i连接到村庄N+1的费用,就可以直接理解为打井的费用Wi 其余部分使用Kruskal最小生成树即可 1 /* 2 Written By StelaYuri 3 */ 4 #include<cstdio> 5 #include<algorithm&

ZJNU 1367 - Party--中高级

寻找从i到X,再从X到i的最短路 可以在正向图中从X开始跑一遍最短路,每个点的距离dis1[i]当作从X回到点i的距离 再将图反向从X再跑一遍,每个点的距离dis2[i]当作从i到点X的距离 最后搜索dis1[i]+dis2[i]值最大的输出 1 /* 2 Written By StelaYuri 3 */ 4 #include<bits/stdc++.h> 5 #define INF 0x3f3f3f3f 6 using namespace std; 7 typedef pair<sh

ZJNU 1538 - YN!ngC的取子游戏--高级

Nim博弈 因为移动到第0阶会消失 所以可以得到从最后一个人操作必定是把第1阶所有子全部移动到第0阶 递推可得,最后一个能把奇数阶的子移动到偶数阶上的人将会必胜 所以这个必胜条件就是奇数阶上的子全部为0 拿奇数阶进行Nim博弈即可 1 #include<stdio.h> 2 int main(){ 3 int n,i,a,s=0; 4 scanf("%d",&n); 5 for(i=1;i<=n;i++){ 6 scanf("%d",&am

BZOJ 1020 安全的航线flight

Description 在设计航线的时候,安全是一个很重要的问题.首先,最重要的是应采取一切措施确保飞行不会发生任何事故,但同时也需要做好最坏的打算,一旦事故发生,就要确保乘客有尽量高的生还几率.当飞机迫降到海上的时候,最近的陆地就是一个关键的因素.航线中最危险的地方就是距离最近的陆地最远的地方,我们称这种点为这条航线“孤地点”.孤地点到最近陆地的距离被称为“孤地距离”.作为航空公司的高级顾问,你接受的第一个任务就是尽量找出一条航线的孤地点,并计算这条航线的孤地距离.为了简化问题,我们认为地图是