F、法师康的工人
题目描述
三个法师康的工人每天早上6点到工厂开始到三条产品生产线上组装桔子手机。第一个工人在200时刻开始(从6点开始计时,以秒作为单位)在生产线上开始生产,一直到1000时刻。第二个工人,在700时刻开始,在1100时刻结束。第三个工人从1500时刻工作到2100时刻。期间最长至少有一个工人在生产线上工作的连续时间为900秒(从200时刻到1100时刻),而最长的无人生产的连续时间(从生产开始到生产结束)为400时刻(1100时刻到1500时刻)。
你的任务是用一个程序衡量N个工人在N条产品线上的工作时间列表(1≤N≤5000,以秒为单位)。
·最长的至少有一个工人在工作的时间段
·最长的无人工作的时间段(从有人工作开始计)
输入
输入第1行为一个整数N,第2-N+1行每行包括两个均小于1000000的非负整数数据,表示其中一个工人的生产开始时间与结束时间。
输出
输出为一行,用空格分隔开两个我们所求的数。
样例输入
3
200 1000
700 1100
1500 2100
样例输出
900 400
题解(写的有点繁琐^ v ^)
#include<bits/stdc++.h>
using namespace std;
int N; //N个工人
int x = 0; // 至少有一个工人在工作的最长时间段x
int y = 0; // 无人工作的最长时间段y(从有人工作开始计)
//vector<vector<int> >p(5001,vector<int>(2));//用vector定义二维数组p[][],5001行 2列
int(*p)[2] = new int [5001][2];//正常定义二维数组p[][],5001行 2列
int *c = new int[5001]; // 标记作用
int *d = new int[5001]; // 标记作用
void Sort(){
for(int i=0;i<N;i++) {
for (int j = N-1; j >0; j--) {
if(p[j][0]<p[j-1][0]) {
int temp1=p[j][0];
int temp2=p[j][1];
p[j][0]=p[j-1][0];
p[j][1]=p[j-1][1];
p[j-1][0]=temp1;
p[j-1][1]=temp2;
}
}
}
}
void Seek(){
// 寻找 最长的至少有一个工人在工作的时间段 x
for(int j = 0;j<N;j++){
// 标记为 1 的表明在前面已经走过
if(c[j] == 1) continue;
c[0] = 1;
int a = p[j][0]; // 最长时间段的起始时间
int b = p[j][1]; // 最长时间段的结束时间
int x1 = b - a; //最长时间段
for(int i=1;i<N;i++){
// 如果两个时间段交叉相接,更新数据
if(p[i][0] < b && p[i][1] > b){
x1 = x1 + p[i][1] - b;
b = p[i][1];
// 如果这个时间段和前面连接过,就标记为 1
c[i] = 1;
}
}
if(x < x1) x = x1;
}
// 寻找 最长的无人工作的时间段 y(从有人工作开始计)
int tmp = p[0][1]; // 前面的最后时间节点
for(int i = 1;i< N;i++){
if(d[i] == 1) continue;
// 这个时间段与前面的最后时间节点之间有无人工作的时间
if(p[i][0] > tmp){
if(y < p[i][0] - tmp) y = p[i][0] - tmp;
tmp = p[i][1];
}
else if(p[i][1] <= tmp){
//这个时间段最后时间节点小于前面的最后时间节点 ,就忽略它
d[i] =1;
}
else {
// 如果交叉,就更新数据
tmp = p[i][1];
}
}
}
int main(){
// 初始化
cin>>N;
for(int i=0;i<N;i++){
cin>>p[i][0]>>p[i][1];
}
memset(c, 0, sizeof(c));
memset(d, 0, sizeof(d));
//按照开始时间从小到大排序
Sort();
//寻找最长时间段
Seek();
cout<<x<<" "<<y;
return 0;
}