ZOJ 1610 Count the Colors(线段树)

版权声明:本文是博主乱写的文章,可以随便转载 https://blog.csdn.net/weixin_43768644/article/details/89386017

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=610

解题思路:思路跟我之前写的POJ 2528差不多。

https://blog.csdn.net/weixin_43768644/article/details/89341259

区别是这题是要输出所有看得见的颜色,以及对应这种颜色有几段。

按顺序讲一下代码。

PART 1:

主函数中:找到建树的右界,以及初始化,build()将区间所有点染为8002

int MAXN = 1;
for (int i = 1;i<=n;i++){
    scanf("%d %d %d",x+i,y+i,c+i);
    x[i]++,c[i]++;
    MAXN  = max(MAXN,y[i]);
}
///init
build(1,1,MAXN);
//memset(tree,0,sizeof tree);
for (int i=0;i<=8000;i++) ans[i] = sum[i] = 0;

for (int i = 1;i<=n;i++){
    if (x[i]<=y[i]) update(x[i],y[i],c[i],1,1,MAXN);
}

主函数外:

对于每次给出区间进行更新,初始都染色为8002

这样给出 2

               1 3 1

               6 8 1

这样的数据就没有问题了,之前我初始化为0应该就是一直wa在这个地方 。看一下我那个poj2528题解应该就能体会到了。 维护的是一段区间内存在的颜色,如果一段区间是一种颜色中间却断了很多段,按照之前的思路,统计出的答案会是1,显然错误。这里把初始化的无色当做一种颜色,就没问题了。

#define mid int m = l+r>>1
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define tl tree[rt<<1]
#define tr tree[rt<<1|1]
void push_up(int rt)
{
    if (tl==-1||tr==-1) tree[rt] = -1;
    else if (tl!=tr) tree[rt] = -1;
}

void update(int L,int R,int c,int rt,int l,int r)
{
    if (L<=l && r<=R){
        tree[rt] = c;
        return ;
    }
    if (tree[rt] > 0) tl = tr = tree[rt];
    mid;
    if (L<=m) update(L,R,c,lson);
    if (R>m)  update(L,R,c,rson);
    push_up(rt);
}

PART 2:

dfs遍历树得到答案,用了差分标记

void dfs(int rt,int l,int r)
{
    if (tree[rt] > 0){
        sum[l] += tree[rt];
        sum[r+1] -= tree[rt];
        return ;
    }
    if (tree[rt] == -1){
        mid;
        dfs(lson);
        dfs(rson);
    }
}

主函数中:

dfs(1,1,MAXN);

for (int i=2;i<=MAXN;i++) sum[i] += sum[i-1];

int pre = 0;
for (int i=1;i<=MAXN;i++){
    if (sum[i]!=pre){
        ans[sum[i]-1]++;
        pre = sum[i];
    }
}

完整代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#define mid int m = l+r>>1
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define tl tree[rt<<1]
#define tr tree[rt<<1|1]

using namespace std;

const int N = 8000+5;

int tree[N<<2],sum[N],ans[N];
int x[N],y[N],c[N];

void push_up(int rt)
{
    if (tl==-1||tr==-1) tree[rt] = -1;
    else if (tl!=tr) tree[rt] = -1;
}

void update(int L,int R,int c,int rt,int l,int r)
{
    if (L<=l && r<=R){
        tree[rt] = c;
        return ;
    }
    if (tree[rt] > 0) tl = tr = tree[rt];
    mid;
    if (L<=m) update(L,R,c,lson);
    if (R>m)  update(L,R,c,rson);
    push_up(rt);
}

void build(int rt,int l,int r)
{
    if (l==r){
        tree[rt] = 8002;
        return ;
    }
    mid;
    build(lson);
    build(rson);
    push_up(rt);
}

void dfs(int rt,int l,int r)
{
    if (tree[rt] > 0){
        sum[l] += tree[rt];
        sum[r+1] -= tree[rt];
        return ;
    }
    if (tree[rt] == -1){
        mid;
        dfs(lson);
        dfs(rson);
    }
}

int main()
{
    int n;
    while (~scanf("%d",&n)){
        int MAXN = 1;
        for (int i = 1;i<=n;i++){
            scanf("%d %d %d",x+i,y+i,c+i);
            x[i]++,c[i]++;
            MAXN  = max(MAXN,y[i]);
        }
        ///init
        build(1,1,MAXN);
        //memset(tree,0,sizeof tree);
        for (int i=0;i<=8000;i++) ans[i] = sum[i] = 0;

        for (int i = 1;i<=n;i++){
            if (x[i]<=y[i]) update(x[i],y[i],c[i],1,1,MAXN);
        }
        dfs(1,1,MAXN);

        for (int i=2;i<=MAXN;i++) sum[i] += sum[i-1];

        int pre = 0;
        for (int i=1;i<=MAXN;i++){
            if (sum[i]!=pre){
                ans[sum[i]-1]++;
                pre = sum[i];
            }
        }

        for (int i=0;i<=8000;i++)
            if (ans[i]) printf("%d %d\n",i,ans[i]);
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43768644/article/details/89386017
今日推荐