題目鏈接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610
F - Count the Colors
Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.Your task is counting the segments of different colors you can see at last.
The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.
Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:
x1 x2 c
x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.
All the numbers are in the range [0, 8000], and they are all integers.
Input may contain several data set, process to the end of file.
Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.
If some color can't be seen, you shouldn't print it.
Print a blank line after every dataset.
5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
4
0 1 1
3 4 1
1 3 2
1 3 1
6
0 1 0
1 2 1
2 3 1
1 2 0
2 3 0
1 2 1
1 1
2 1
3 1
1 1
0 2
1 1
思路:這道題和poj2528貼海報那道題十分像,只不過那道題是讓你輸出顏色的種類數,這道題是求出每個顏色有幾段。
暴力建線段樹,區間更新,最後查詢的時候都pushdown到子節點查詢就ok。
這道題有幾個坑點
1.題中樣例給的區間是一段,不是一個點。例如:[1,3]代表(1,2)和(2,3)兩段,並不代表1,2,3三段,這一點不注意會段錯誤。
2.每次查詢的區間應該是1~8000,而不是1~n.
最後上代碼:
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#define MAXN 8010
using namespace std;
int a,b,c;
int tree[MAXN<<2];
int ans;
int tmp;
int col[8010];
void pushdown(int p)
{
if(tree[p]!=-1)
{
tree[p<<1]=tree[(p<<1)|1]=tree[p];
}
tree[p]=-1;
}
void update(int p,int l,int r,int x,int y,int a)
{
if(x<=l&&y>=r)
{
tree[p]=a;
return ;
}
if(tree[p]!=-1)
pushdown(p);
int mid=(l+r)>>1;
if(y<=mid)
update(p<<1,l,mid,x,y,a);
else if(x>mid)
update((p<<1)|1,mid+1,r,x,y,a);
else
{
update(p<<1,l,mid,x,mid,a);
update((p<<1)|1,mid+1,r,mid+1,y,a);
}
}
void query(int p,int l,int r)
{
if(l==r)
{
if(tree[p]!=-1&&tree[p]!=tmp) //因爲查的是連續的段,所以和之前顏色不一樣纔算新的一段。
{
col[tree[p]]++;
}
tmp=tree[p];
return ;
}
pushdown(p);
int mid=(l+r)>>1;
query(p<<1,l,mid);
query((p<<1)|1,mid+1,r);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(tree,-1,sizeof(tree));
memset(col,0,sizeof(col));
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
update(1,1,8000,a+1,b,c); //左端點加1解決第一個坑點
}
tmp=-1;
query(1,1,8000); //查詢區間爲1~8000
for(int i=0;i<=8000;i++)
{
if(col[i]!=0)
printf("%d %d\n",i,col[i]);
}
printf("\n");
}
return 0;
}