Description
给定一条长度为m的线段,有n个操作,每个操作有3个数字x,y,z表示把区间[x,y]染成颜色z,询问染完色之后,这条长度为m的线段一共有几种颜色。
规定:线段的颜色可以相同。连续的相同颜色被视作一段。问x轴被分成多少段。
Sample Input
20 //四条,总长度为20
10 19 1
2 9 2
5 13 3
15 17 4
Sample Output
7
Hint
数据规模
N <= 10000
M <= 1000000
分析
同样是线段树的模板题(稍有变式),用一个ans变量记录上一段的颜色,如果与本段的相同,那么就不累加,不同的话就+1。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
typedef long long ll;
using namespace std;
int n,m,x,y,z,ans,a[4000001];
void insert(int k,int l,int r,int x,int y,int c)
{
if(l==x&&r==y)
{
a[k]=c;
return;
}
if(a[k]>=0)
{
a[2*k]=a[2*k+1]=a[k];
a[k]=-1;
}
int mid=(l+r)/2;
if(y<=mid)
{
insert(2*k,l,mid,x,y,c);//a数组就是树上点的编号,左儿子为2*n
}
else if(x>=mid)
{
insert(2*k+1,mid,r,x,y,c);//右儿子为2*n+1
}
else
{
insert(2*k,l,mid,x,mid,c);
insert(2*k+1,mid,r,mid,y,c);
}
}
int cnt(int k,int l,int r)
{
int mid=(l+r)/2;
if(a[k]>=0)
{
int s=1;
if(a[k]==ans) s=0;
ans=a[k];
return s;
}
return cnt(k*2,l,mid)+cnt(k*2+1,mid,r);
}
int main()
{
scanf("%d%d",&n,&m);//必须scanf不然超时呵呵
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&z);
insert(1,1,m,x,y,z);//x,y,z就是cover域
}
ans=-1;
cout<<cnt(1,1,m);
return 0;
}