zoj1610(线段树)

题目连接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610

题意:在0-8000长的线段里面,按先后次序依次覆盖颜色,求最后每种颜色有多少条

线段树功能:区间覆盖。

分析:区间覆盖后将叶子节点信息取出来O(N)扫一遍即可。

注意:线段长度固定为8000,并不是n,否则无限“Segmentation Fault”。

#pragma comment(linker,"/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 10010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int col[N<<2];
int cnt[N],num[N];
void Pushdown(int rt)
{
    if(col[rt]!=-1)
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        col[rt]=-1;
    }
}
void build(int l,int r,int rt)
{
    col[rt]=-1;
    if(l==r)
    {
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int L,int R,int c,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        col[rt]=c;
        return;
    }
    Pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,lson);
    if(m<R)update(L,R,c,rson);
}
void query(int l,int r,int rt)
{
    if(l==r)
    {
        cnt[l]=col[rt];
        return;
    }
    Pushdown(rt);
    int m=(l+r)>>1;
    query(lson);
    query(rson);
}
int main()
{
    int n,m;;
    int a,b,c;
    while(scanf("%d",&n)>0)
    {
        build(1,8000,1);
        m=n;
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(a==b)continue;
            update(a+1,b,c,1,8000,1);
        }
       query(1,8000,1);
       FILL(num,0);
       for(int i=1;i<=8000;i++)
       {
           while(cnt[i]==cnt[i+1]&&i<8000)i++;
           if(cnt[i]!=-1)
           num[cnt[i]]++;
       }
       for(int i=0;i<=8000;i++)
       {
           if(num[i])printf("%d %d
",i,num[i]);
       }
       puts("");
    }
}
View Code
原文地址:https://www.cnblogs.com/lienus/p/4240344.html