大体题意:
你在一个考场里做题,做题时间是t0~t1,有n (n <= 10000)个监考员,告诉你每一个监考员的入场时间和出场时间,现在你可以给一定量的监考员进行染色,使得考场内只有一个且染色监考员的总时间不小于 你做题时间的2/3,如果可行输出你染色的监考员,如果不可行输出0! 输入保证在你做题时间至少有一个监考员!
思路:
构造法!
知道了每个监考员的入场时间和出场时间,我们可以把它看成一个区间! 最后要求你保留一些区间,使得这个区间只有一个线段的数值总和不小于考试时间 的2/3.
我们把 去掉后没有空白的区间给删掉!这样最后给剩下的区间按照左端点进行排序,那么第i 个区间和第i+1个区间一定相交,并且第i 个区间一定不和第i+2个区间相交,否则第i+2个区间或者第i+1个区间可以被删掉!
这样我们选出所有奇数号的区间,这些区间一定都不相交,加起来如果大于2/3 输出!
如果上述情况不合适 那么我们在加偶数号区间,这些区间同样也都不想交 ,加起来如果大于2/3 输出!
如果还是不大于2/3
那么我们来看看全选的时间!
令a = 奇数号的区间时间总和!
令b = 偶数号区间的时间总和!
令T 为你的做题时间!
如果全选,那么剩下的“单独时间” 的总和为 T-a + T - b(这个式子画个图就很明了了!)
现在a < 2*T/3 b < 2*T/3
那么单独时间 为2*T - (a+b) >= 2*T/3
所以说 如果上述奇偶都不合理的情况下 全选一定有解! 所以此题一定有解!
因为是浮点数 注意好精度控制就好了!
贴个图 帮助大家理解:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const double eps = 1e-10;
const double inf = 1e18;
const int maxn = 10000 + 7;
double t0,t1;
double dcmp(double a,double b){ // 比较浮点数大小
if (fabs(a-b) < eps) return 0;
if (a > b) return 1;
return -1;
}
struct Node{
double l,r;
int id;
void read() { scanf("%lf %lf",&l, &r);}
bool operator < (const Node& rhs) const {
return dcmp(l,rhs.l) == -1 || (dcmp(l,rhs.l) == 0 && dcmp(r,rhs.r) == 1);
}
}p[maxn];
vector<int>ans;
int main(){
while(~scanf("%lf %lf",&t0, &t1)){
int n;
ans.clear();
double T = 2.0*(t1-t0)/3.0; // 总时间值!
scanf("%d",&n);
for (int i = 0; i < n; ++i){
p[i].read();
p[i].id = i+1;
}
sort(p,p+n);
int len = 0;
for (int i = 0; i < n; ++i){
bool ok = 0;
if (len == 0){
ans.push_back(i);
ok = 1;
len++;
}
else if (len == 1){
int id = ans[0];
if (dcmp(p[i].l,p[id].l) == 1 && dcmp(p[i].r,p[id].r) == 1) ans.push_back(i),ok = 1,++len;
}
else {
int laa = ans[len-2];
int la = ans[len-1];
if (dcmp(p[laa].r,p[i].l) == -1 && dcmp(p[i].r,p[la].r) == 1){
ans.push_back(i);
++len;
ok = 1;
}
else if (dcmp(p[laa].r,p[i].l) != -1 && dcmp(p[i].r,p[la].r) != -1){
ans.pop_back();
ans.push_back(i);
ok = 1;
}
}
if (!ok) continue;
int cur = i;
while(i+1 < n && dcmp(p[i+1].l,p[cur].l) == 0)++i;
}
double sum1 = 0,sum2 = 0; // 分奇数偶数的形式来讨论!
int cnt1=0,cnt2=0;
for (int i = 0; i < ans.size(); i+=2){
int id = ans[i];
sum1 += p[id].r - p[id].l;
++cnt1;
}
if (dcmp(sum1,T) != -1) {
printf("%d\n",cnt1);
for (int i = 0; i < ans.size(); i+=2){
int id = ans[i];
printf("%d\n",p[id].id);
}
}
else {
for (int i = 1; i < ans.size(); i+=2){
int id = ans[i];
sum2 += p[id].r - p[id].l;
++cnt2;
}
if (dcmp(sum2,T) != -1) {
printf("%d\n",cnt2);
for (int i = 1; i < ans.size(); i+=2){
int id = ans[i];
printf("%d\n",p[id].id);
}
}
else {
printf("%d\n",ans.size());
for (int i = 0; i < ans.size(); ++i){
printf("%d\n",p[ans[i]].id);
}
}
}
}
return 0;
}
/**
0 6
3
0 3
2 5 4 6
**/
1105. Observers Coloring
Memory limit: 64 MB
Input
Output
Sample
input | output |
---|---|
0.0 20.0 7 1.0 1.5 0.0 10.0 9.0 10.0 18.0 20.0 9.0 18.0 2.72 3.14 19.0 20.0 | 3 2 5 7 |
Problem Source: Tetrahedron Team Contest May 2001
All submissions (3672) All accepted submissions (639) Solutions rating (477)