题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610
题目大意:在一条线上绘制一些彩色片段,一些先前绘制的片段可能被后续的一些片段覆盖。您的任务是计算最后可以看到的不同颜色的片段。
每个数据集的第一行恰好包含一个整数n,1 <= n <= 8000,等于彩色段的数量。以下n行中的每一行由正好由单个空格分隔的3个非负整数组成:x1 x2 c
x1和x2表示段的左端点和右端点,c表示段的颜色。
所有数字都在[0,8000]范围内,它们都是整数。输入可能包含多个数据集,处理到文件末尾。
输出:输出的每一行应包含一个颜色索引,可以从顶部看到,按照这种颜色的分段计数,它们应根据颜色索引打印。如果看不到某种颜色,则不应打印。
在每个数据集后打印一个空行。
之前遇到过数组含义的问题,这里如果对x, y区间染c色,UP(1, x, y, c)更新。
那么此时节点的含义是区间的端点。
所以到最后,知道端点的含义并不知道区间的颜色。就会认为最后只能看见两种颜色。
如果我们把节点i的含义改[i-1, i]区间的颜色,那么就可以了,UP(1, x+1, y, c)更新。
然后改完还是WA了。有个奇怪的错误,就是建树的时候,我建了8001个节点WA了。改成8000个就AC。不知道这是为什么。
思考:注意对数组和节点代表的含义。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define MAX_NODE 800005
#define MAX_ 200005
struct NODE
{
int l, r;
}node[MAX_NODE];
int f[MAX_]; //记录节点i的node结构体数组下标f[i]
int add[MAX_NODE];
void BT(int i, int l ,int r) //建树
{
node[i].l=l;
node[i].r=r;
if(l==r) //根节点
{
f[l]=i;
return;
}
BT((i<<1), l, (l+r)/2); //建左子树
BT((i<<1)+1, (l+r)/2+1, r);//建右子树
}
void upadd(int i)
{
if(add[i])
{
add[i<<1]=add[i]; //把左右子的add标记进行更新
add[(i<<1)+1]=add[i];
add[i]=0; //清零父节点的add标记
}
}
void UP(int i, int l, int r, int c)//更新
{
if(node[i].l==l&&node[i].r==r)//找到更新区间
{
add[i]=c; //更新add标记
return;
}
if(node[i].l==node[i].r) //叶子节点
{
add[i]=c;
return;
}
upadd(i); //把此本节点的add往下移动
int mid=(node[i].l+node[i].r)/2;//继续寻找区间
if(r<=mid) //全在左区间
{
UP(i<<1, l, r, c);
}
else if(l>mid) //全在右区间
{
UP((i<<1)+1, l, r, c);
}
else
{
UP(i<<1, l, mid, c);
UP((i<<1)+1, mid+1, r, c);
}
}
void FD(int i, int l, int r) //查找
{
if(l==r)
{
return;
}
upadd(i);
FD(i<<1, l, (l+r)/2);
FD((i<<1)+1, (l+r)/2+1, r);
}
//建树 BT(1, 1 ,n);节点1-n
//查询 FD(1, a, b);[a, b]的信息
//更新 UP(1, a, b, c);//把区间的add+=a
int c[8001];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(c, 0, sizeof(c));
memset(add, 0, sizeof(add));
BT(1, 1, 8000);
for(int i=1;i<=n;i++)
{
int a, b, c;
scanf("%d%d%d",&a,&b,&c);
UP(1, a+1, b, c+1);
}
FD(1, 1, 8000);
int ans=0;
for(int i=1;i<=8000;i++)
{
if(add[f[i]]!=add[f[i-1]]&&add[f[i]]!=0)
{
c[add[f[i]]-1]++;
}
}
for(int i=0;i<=8000;i++)
{
if(c[i]!=0)
{
printf("%d %d\n",i, c[i]);
}
}
printf("\n");
}
return 0;
}