版权声明:转载者乖乖♂站好 https://blog.csdn.net/Eric1561759334/article/details/82707566
Description
给定一条长度为m的线段,有n个操作,每个操作有3个数字x,y,z表示把区间[x,y]染成颜色z,询问染完色之后,这条长度为m的线段一共有几种颜色。规定:线段的颜色可以相同。连续的相同颜色被视作一段。问x轴被分成多少段。
Input
Output
Sample Input
4 20 //四条,总长度为20
10 19 1
2 9 2
5 13 3
15 17 4
Sample Output
7
Hint
数据规模
N <= 100000
M <= 1000000
思路
我以前写的线段树都是假的!!(改了我2个中午)
对于每一段,维护一个左节点,一个右节点,表示每一段左右端的颜色
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,a[1000077*3],c,d;
void ins(int st,int ed,int l,int r,int c,int u)
{
if(l>r) return;
if(c==a[u]) return;
if(st==l&&ed==r) a[u]=c;else
{
if(a[u]!=-1) a[u*2+1]=a[u],a[u*2]=a[u],a[u]=-1;
int mid=(st+ed)>>1;
if(r<=mid) ins(st,mid,l,r,c,u*2);else
if(l>mid) ins(mid+1,ed,l,r,c,u*2+1);else
{
ins(st,mid,l,mid,c,u*2);
ins(mid+1,ed,mid+1,r,c,u*2+1);
}
}
}
int query(int l,int r,int u,int &lc,int &rc)
{
int lt=0,rt=0;
if(a[u]!=-1)
{
rc=lc=a[u];
return 1;
}
if(l==r) return 1;
int mid=(l+r)>>1,s=query(l,mid,u*2,lc,lt)+query(mid+1,r,u*2+1,rt,rc);
return s-(lt==rt?1:0);
}
int main()
{
// scanf("%d",&n);
scanf("%d%d",&m,&n);
a[n+1]=2147483647; a[0]=2147483647;
for(int i=1; i<=m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ins(1,n,x,y,z,1);
}
printf("%d",query(1,n,1,c,d));
}