小J有一把尺子。一天MPS闲得无聊,拿了一桶油漆,用刷子在上面刷了N下,刷第i次有一个正整数范围(ai,bi),表示从尺子的刻度ai刷到刻度bi。此时ai到bi这个区间里的油漆层数+1。
为了去掉这些油漆,小J找来了一把刀,每次可以从尺子的一个整数刻度刮到另一个整数刻度。每刮一刀都有一个力度,如力度为3时可以一次刮掉3层油漆。但不能损坏尺子。比如有2层油漆的地方就不能用力度3来刮。
小J想知道最少要刮多少次。
第一行,一个整数N
第2...N+1行,第i+1行两个整数ai,bi。
一行,最少刮多少次。
3
1 4
2 5
1 5
2
【样例解释】
刮2刀,第一次刮区间(1,5),力度为2,第一次刮区间(2,4),力度为1。
【数据范围】
40%的数据N<=2000
100%的数据N,ai,bi<=10^5
于是按照积木大赛的算法改了一下,但是失败了···
但是和正确的算法也有异曲同工之妙
事实上,我们只需要在读入每个区间时【对区间的左端点a[k]+1,右端点a[k]-1,最后统计是正数多还是负数多即可】
为什么这样可以呢?我们举一个例子:
第一个区间【1,3】
第二个区间【1,5】
那么图像是这样的
XXX
XXXXX
对应数字为
1 0 -1 0 -1
结合积木大赛的思路,由于负数有两个,有两处下降,那么至少两次才能刮完。更多情况,可以以此深入理解。
code
//codevs3371 刮油漆
//copyright by ametake
#include
#include
#include
using namespace std;
const int maxn=500000+10;
int p[maxn];
int n;
int main()
{
scanf("%d",&n);
int a,b;
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
p[a]++;
p[b]--;
}
int po=0,ne=0;
for (int i=1;i<=maxn-9;i++)
{
if (p[i]>0) po++;
if (p[i]<0) ne++;
}
if (po>ne) printf("%d\n",po);
else printf("%d\n",ne);
return 0;
}