ZOJ 1610 线段树

要求:给若干个左右端点已知的线段涂色,同一位置新的颜色会覆盖旧的颜色,求最后能看到的颜色有哪几种,并且能看到的同一种颜色有几段。

方法:线段树裸题 查找注意

WA到死的原因如下:

1.区间最大8000不需要离散化,而我受上一道海报题影响用了离散化。

2.因为所求答案不同故更新方式不同,而我受上一道海报题影响用了倒序涂色。

3.区间涂色的意思是:涂了[1,2],[3,4]还有[2,3]未涂,重在连续性。

4.点涂色的意思是:涂了[1,2],[3,4]后,[2,3]已涂,重在离散性。

5.3变4的方法是左端点+1,即可视为离散端点。

6.[0,2]和[3,4]是两端,但是由于没有注意就输出了1段。

一道会写的裸题不注意的就这么多,自己还是太弱了,每天还是需要坚持训练。

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
int k,a,b,c,ans[30005],temp,tempr;
int ql[30005],qr[30005],qc[30005],color[30005];
//color[i]=-1表示空 color[i]=-2表示非同一个颜色 
//color[i]>=0表示颜色 
void update(int i,int l,int r)
{
	int m=l+(r-l)/2;
	if(a<=l&&r<=b) 
	{
		color[i]=c;
		return;
	}
    if(l>=r) return;
    //向下传递涂色信息 
	if(color[i]>=0)
	{
	 color[i*2]=color[i];
	 color[i*2+1]=color[i];	
	}
	//若未涂满色 向下搜索 
	if(a<=m) update(i*2,l,m);
    if(b>m)  update(i*2+1,m+1,r);	
    
    //若左右孩子非同色 或 左右孩子均自身为非同色 则自身非同色 
	if(color[i*2]!=color[i*2+1]||color[i*2]==-2&&color[i*2+1]==-2)
	  color[i]=-2;  
}
void query(int i,int l,int r)
{
    int m=l+(r-l)/2;
	//从左到右搜索涂色结点 若不同则+1 
	if(color[i]>=0&&color[i]!=temp||
	   color[i]>=0&&color[i]==temp&&l>tempr+1)
	{
		temp=color[i];
		tempr=r;
		ans[color[i]]++;
		return;
	}
	if(color[i]>=0&&color[i]==temp&&l==tempr+1)
	{
		tempr=r;
		return;
	}
	if(color[i]>=0)
	{
	 color[i*2]=color[i];
	 color[i*2+1]=color[i];	
	}
	if(color[2*i]!=-1) query(2*i,l,m);
	if(color[2*i+1]!=-1) query(2*i+1,m+1,r);
}
int main()
{
	int i,j,k,n,cnt; 
	while(scanf("%d",&n)!=EOF)
	{
	   	memset(color,-1,sizeof(color));
	   	cnt=0;
	   	for(j=1;j<=n;j++)//输入海报的左右端点 
	   	{
	   	  scanf("%d",&ql[j]);
	   	  ql[j]++;	
	   	  scanf("%d",&qr[j]);
	   	  scanf("%d",&qc[j]);
	   	  a=ql[j],b=qr[j],c=qc[j];
	   	  update(1,1,8000);
	    }
		temp=tempr=-3;
		memset(ans,0,sizeof(ans));
	    query(1,1,8000);
	    for(i=0;i<=8000;i++)
	      if(ans[i]>0)  printf("%d %d\n",i,ans[i]); 
	    printf("\n");  
	}
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/83451161
今日推荐