初见安。
:)
整数区间
Description
我们定义一个整数区间[a,b]:是一个从a开始至b 结束的连续整数的集合。编一个程序,对给定的 n(n≤1000
)个区间,找出满足下述条件的所含元素个数最少的集合中元素的个数:对于所给定的每一个区间,都至少有两个
不同的整数属于该集合。
Input
第一行一个正整数n,接下来有n行,每行给定一个区间的a,b值。
Output
一个正整数,满足条件的集合所包含的最少元素个数
Sample Input
4
3 6
2 4
0 2
4 7
Sample Output
4
//选取[1,2,4,6]这四个元素
Sol
呜呜呜贪心果然是最难的算法QAQ刚开始拿到这个题差点没读懂。读懂了过后大脑一片空白。乱整了半个小时就放弃了。
这个看似往n^2暴力的方向想都想不出来的题,其实只需要考虑最后的情况就可以了——如果一个区间都到了最后两个整数了还没有数被选中,那么最后两个数一定要选。所以可以直接枚举这些区间并集里的数,看看有没有在某一个区间内起到了上述的那种关键作用,有则选,无则不选。所以对于每一个区间,我们需要一个size计算剩下的大小以及cnt计算这个区间内选中了多少个数。
没了。QAQ真的,没了。
#include<bits/stdc++.h>
#define maxn 1005
using namespace std;
struct node
{
int l, r, size, cnt;
}a[maxn];
int n, ce = 0, fl = 0x3f3f3f3f;
int ans = 0;
bool flag;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d%d", &a[i].l, &a[i].r), a[i].size = a[i].r - a[i].l + 1, fl = min(a[i].l, fl), ce = max(ce, a[i].r);
for(int i = fl; i <= ce; i++)
{
flag = 0;
for(int j = 1; j <= n; j++)
{
if(a[j].l <= i && i <= a[j].r)//包含了i,和i有关的区间才考虑
{
if(a[j].size == 2 && !a[j].cnt) flag = 1;//剩两个,没选过
else if(a[j].size == 1 && a[j].cnt == 1) flag = 1;//剩一个,选一个。都是必选情况
a[j].size--;
}
}
if(flag)//如果这个数选中了,那么和这个数有关的区间的cnt也都要改变
{
ans++;
for(int j = 1; j <= n; j++) if(a[j].l <= i && i <= a[j].r) a[j].cnt++;
}
}
printf("%d\n", ans);
return 0;
}
其本质简洁的过分。直到最后我都没有想过把这个题写出来……
奶牛的聚集 Great Cow Gather
这个题时间不够了【就是debug时间过长以至于最后dfs的时候顺序出了问题都没有来得及发现】
其实我看到最后一组数据过了但是样例没过就想着还能骗几个分吧大不了WA一些结果就真的只有最后一组过了……
传送:洛谷P2986 伟大的奶牛聚集 Great Cow Gather
坑爹的GPS Dueling GPS's
这个题……我一开始以为我可以做出来……然后发现不会处理多条最短路……样例没过但最后一组数据过了的情况再现。
传送:洛谷P3106 GPS的决斗Dueling GPS's
是的这次考试就20分。【理直气壮】而且还是看起来很像最后一组数据打表的那种【然而我没有……】
总结写完了,溜了溜了。