线段树练习题三
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));
}