一个区间取点问题,按右端点排序。从右端开始标注,保证每段区间都有K个标注点,小于K的区间则保证其区间的点全部被标注,在标注时注意因为范围是-10000~10000,因此需要用一个20000的数组存,需将整体范围往右移动10000(例:标注-10000为a[0] = 1,标注0为a[10000] = 1),保证其全部大于零。
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct point
{
int x, y;
} pot[1002];
int cmp(const void *a, const void *b)
{
point *aa = (point *)a;
point *bb = (point *)b;
if(aa->y != bb->y)
return aa->y > bb->y ? 1 : -1;
return aa->x > bb->x ? 1 : -1;
}
int ascend_cmp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
const int chr = 10000;
int main()
{
#ifdef test
freopen("in.txt", "r", stdin);
#endif
int t, k, n, save[20002], flag[20002];
scanf("%d", &t);
while(t--)
{
int cct = 0, xx, yy;
scanf("%d%d", &k, &n);
for(int i = 0; i < n; i++)
{
scanf("%d%d", &xx, &yy);
if(xx < yy) // 保证所有的左端点都小于右端点
{
pot[i].x = xx;
pot[i].y = yy;
}
else
{
pot[i].x = yy;
pot[i].y = xx;
}
}
qsort(pot, n, sizeof(pot[0]), cmp);
memset(flag, 0, sizeof(flag));
for(int i = 0; i < n; i++)
{
int fct = 0;
for(int j = pot[i].x; j <= pot[i].y; j++) // 检查此段区域内有多少点是已经被标注过的
if(flag[j + chr])
{
fct++;
if(fct == k)
break;
}
if(fct == k)
continue;
for(int j = pot[i].y; j >= pot[i].x; j--)
{
if(!flag[j + chr])
{
flag[j + chr] = 1;
save[cct++] = j;
fct++;
}
if(fct == k)
break;
}
}
qsort(save, cct, sizeof(save[0]), ascend_cmp);
printf("%d\n", cct);
for(int i = 0; i < cct; i++)
printf("%d\n", save[i]);
if(t)
puts("");
}
return 0;
}