【SSLGZ】线段树练习题三

版权声明:转载者乖乖♂站好 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));
}

猜你喜欢

转载自blog.csdn.net/Eric1561759334/article/details/82707566