SSL2646 线段树练习题3【线段树】

SSL2646 线段树练习题3【线段树】_第1张图片

思路:

与上一题一样,
仍然定义tree如下:
tree=-1表示该区间由多种颜色组成。
tree>=0表示该区间只有一种单一的颜色cover。

插入操作与线段树 3 3 3一样
值得注意的是统计操作

long long ccount(long long x,long long l,long long r,long long &lc,long long &rc)
{
	long long lt=0,rt=0;
	if(tree[x]!=-1)     //如果当前节点只有一种颜色
	 {
	 	lc=rc=tree[x];    //传递
	 	return 1;   //就当成一段
	 }
	if(l==r)   //如果是叶子结点,就是一种颜色
	  return 1;
	long long mid=(l+r)/2;
	long long sum=ccount(x*2,l,mid,lc,lt)+ccount(x*2+1,mid+1,r,rt,rc);
	//把当前节点的左右子节点的颜色段全部加上
	if(rt==lt)  //如果当前节点的左右子节点颜色重复
	  return sum-1;  //就剪去一个多算的
	else
	  return sum;
}

全部代码:

#include
#include
#include
#include
using namespace std;
long long n,m,l[4000010],r[4000010],w[4000010];
long long tree[400010];
void insert(long long a,long long b,long long l,long long r,long long x,long long color)
{
	if(a>b)
	  return;
	if(tree[x]==color)
	  return;
	if(a==l&&b==r)
	  tree[x]=color;
    else
	 {
	 	long long mid=(l+r)/2;
	 	if(tree[x]!=-1)
		 {
	 	   tree[2*x]=tree[2*x+1]=tree[x];
		   tree[x]=-1;
	 	 }
		if(b<=mid)
	  	  insert(a,b,l,mid,x*2,color);
		else if(a>mid)
	  	  insert(a,b,mid+1,r,x*2+1,color);
		else
	     {
	 	   insert(a,mid,l,mid,x*2,color);
	 	   insert(mid+1,b,mid+1,r,x*2+1,color);
	     }
	 }
}
long long ccount(long long x,long long l,long long r,long long &lc,long long &rc)
{
	long long lt=0,rt=0;
	if(tree[x]!=-1)     //如果当前节点只有一种颜色
	 {
	 	lc=rc=tree[x];    //传递
	 	return 1;   //就当成一段
	 }
	if(l==r)   //如果是叶子结点,就是一种颜色
	  return 1;
	long long mid=(l+r)/2;
	long long sum=ccount(x*2,l,mid,lc,lt)+ccount(x*2+1,mid+1,r,rt,rc);
	//把当前节点的左右子节点的颜色段全部加上
	if(rt==lt)  //如果当前节点的左右子节点颜色重复
	  return sum-1;  //就剪去一个多算的
	else
	  return sum;
}
int main()
{
    cin>>n>>m;
    for(long long i=1; i<=n; i++)
     {
     	scanf("%lld%lld%lld",&l[i],&r[i],&w[i]);
     	insert(l[i],r[i],1,m,1,w[i]);
     }
    long long l=0,ling=0;  //因为是指针,所以要定义两个变量
    cout<<ccount(1,1,m,l,ling); 
    return 0;
}

你可能感兴趣的:(题解,线段树)