【SSL 2646】线段树练习题三【线段树变式】

线段树练习题三

Time Limit:10000MS Memory Limit:65536K
Case Time Limit:1000MS

Description

给定一条长度为m的线段,有n个操作,每个操作有3个数字x,y,z表示把区间[x,y]染成颜色z,询问染完色之后,这条长度为m的线段一共有几种颜色。规定:线段的颜色可以相同。连续的相同颜色被视作一段。问x轴被分成多少段。

Input

Output

Sample Input

20   //四条,总长度为20
10 19 1
2 9 2
5 13 3
15 17 4

Sample Output

7

在这里插入图片描述

分析:

用一个临时变量ans记录上一个贡献的颜色是否与当前相同
是的就贡献0 不一样就贡献1

CODE:

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,m,x,y,z,ans,f[4000010];
void insert(int dep,int l,int r,int x,int y,int color){
	if(l==x&&r==y){
		f[dep]=color;  //先染色
		return;
	}
	if(f[dep]>=0){
		f[2*dep]=f[2*dep+1]=f[dep];
		f[dep]=-1;
	}
	int mid=(l+r)/2;
	if(y<=mid) insert(2*dep,l,mid,x,y,color);
    else if(x>=mid) insert(2*dep+1,mid,r,x,y,color);  //不同情况不同递归
	else 
	{
		insert(2*dep,l,mid,x,mid,color);
		insert(2*dep+1,mid,r,mid,y,color);
	}
}
int find(int dep,int l,int r){
	int mid=(l+r)/2;
	if(f[dep]>=0)
	{
		int q=1;
		if(f[dep]==ans)   //不同贡献
			q=0;
		ans=f[dep];
		return q;
	}
	return find(dep*2,l,mid)+find(dep*2+1,mid,r);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		insert(1,1,m,x,y,z);
	}
	ans=-1; printf("%d",find(1,1,m));
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/107516522