PKU 2528
题型:线段树
描述:长为L的报栏上按顺序贴广告[a,b],统计不同的广告数。
思路:数据要离散化处理,然后区间的更新和统计。
离散化方法参考:
离散化代码参考:
代码
//1408K 63MS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NL 32768
struct Seg {
int l, r, no;
}t[NL*2];
struct Ban {
int s, e, no;
int s1, e1;
bool isLeft;
}b[10001];
struct R {
int a, no;
bool isLeft;
}ref[20001];
bool flg[10001];
int cnt;
int cmp(const void *a, const void *b)
{
return ((struct R *)a)->a - ((struct R *)b)->a;
}
void build(int l, int r, int k)
{
t[k].l = l;
t[k].r = r;
t[k].no = -1;
int md = (l+r)>>1, k0 = k<<1;
if (l + 1 < r) {
build(l, md, k0);
build(md, r, k0+1);
}
}
void mody(int l, int r, int no, int k)
{
if (t[k].l == l && t[k].r == r) {
t[k].no = no;
return;
}
int md = (t[k].l+t[k].r)>>1, k0 = k<<1;
if (t[k].no >= 0) {
t[k0].no = t[k0+1].no = t[k].no;
t[k].no = -1;
}
if (r <= md)
mody(l, r, no, k0);
else if (l >= md)
mody(l, r, no, k0+1);
else {
mody(l, md, no, k0);
mody(md, r, no, k0+1);
}
}
void count(int l, int r, int k)
{
if (t[k].l == l && t[k].r == r && t[k].no >= 0) {
if (!flg[t[k].no]) {
flg[t[k].no] = 1;
cnt++;
}
return;
}
int md = (t[k].l+t[k].r)>>1, k0 = k<<1;
if (r <= md)
count(l, r, k0);
else if (l >= md)
count(l, r, k0+1);
else {
count(l, md, k0);
count(md, r, k0+1);
}
}
int main()
{
int n, T;
int i, j;
// freopen("in.txt", "r", stdin);
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (i=0, j=0; i<n; i++) {
scanf("%d%d", &b[i].s, &b[i].e);
b[i].no = i;
ref[j].a = b[i].s, ref[j].isLeft = true, ref[j++].no = i;
ref[j].a = b[i].e, ref[j].isLeft = false, ref[j++].no = i;
}
//离散化
qsort(ref, j, sizeof(ref[0]), cmp);
int p, m = 1, rf = ref[0].a;
p = ref[0].no;
if (ref[0].isLeft) b[p].s1 = m;
else b[p].e1 = m;
for (i=1; i<j; i++) {
if (rf != ref[i].a) {
rf = ref[i].a;
m++;
}
p = ref[i].no;
if (ref[i].isLeft) b[p].s1 = m;
else b[p].e1 = m;
}
//end离散化
build(1, m+1, 1);
for (i=0; i<n; i++) {
mody(b[i].s1, b[i].e1+1, b[i].no, 1);
}
memset(flg, 0, sizeof(flg));
cnt = 0;
count(1, m+1, 1);
printf("%d\n", cnt);
}
return 0;
}