线段树增强训练题 ZOJ1610 Count the Colors

26 篇文章 0 订阅
20 篇文章 0 订阅

线段树增强训练题 ZOJ1610 Count the Colors

线段树增强训练,啊啊啊,我还是太菜了

这道题调试起码4个小时,明明一道很简单的题目。。。。

题意也看了好久,与一开始还读错题意了,但是问题不大,在原来的代码上改改也可

题意:对一段长为8000的线段进行染色,颜色有8000种,每次对区间[l,r]进行染色,进行n次操作后,问你每一种颜色有几段。

很明显的区间修改和查询,不假思索就动起手来、

但是要注意对于 相同颜色的[1,2]和[3,4]区间属于两段。

我们将每个节点视为一个的区间,对线段树的节点进行染色,如果该节点下的子节点颜色不同就将该节点视为颜色不明确(我们用-1表示)

基本思路是这样,我们先上AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=8001;
int n,le[maxn],ri[maxn],c[maxn],ans[maxn],vis[maxn];
struct Node{
    int col;
}tree[maxn<<2];
void build(int l,int r,int node){
    if(l==r){
        tree[node].col=-1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,node<<1);
    build(mid+1,r,node<<1|1);
    tree[node].col=-1;
}
void push_down(int node){
    if(tree[node].col>=0){
        tree[node<<1].col=tree[node].col;
        tree[node<<1|1].col=tree[node].col;
    }
return;
}
void change(int fl,int fr,int x,int l,int r,int node){
    push_down(node);
    if(fr<l || fl>r || tree[node].col==x)
        return;
    if(fl<=l && fr>=r){
        tree[node].col=x;
        return ;
    }
    int mid=(l+r)>>1;
    change(fl,fr,x,l,mid,node<<1);
    change(fl,fr,x,mid+1,r,node<<1|1);
    if(tree[node<<1].col==tree[node<<1|1].col)
        tree[node].col=tree[node<<1].col;
    else
        tree[node].col=-1;
}
void findx(int l,int r,int node){
    if(tree[node].col>=0)
    {
        for(int i=l;i<=r;i++)
            vis[i]=tree[node].col;
        return;
    }
    if(l!=r){
        int mid=(l+r)>>1;
        findx(l,mid,node<<1);
        findx(mid+1,r,node<<1|1);
    }
}
int main(){
    while (~scanf("%d",&n)){
        int len=0,cc=0;
        for(int i=1;i<=n;i++){
            scanf("%d %d %d",&le[i],&ri[i],&c[i]);
            len=max(ri[i],len);
            cc=max(cc,c[i]);
        }
        build(1,len,1); 
        for(int i=1;i<=n;i++){
            change(le[i]+1,ri[i],c[i],1,len,1);
        }
        fill(vis,vis+1+len,-1);
        fill(ans,ans+1+cc,0);
        findx(1,len,1);
        for (int i = 1; i <=len; i++)
        {
            if(vis[i]!=vis[i-1] && vis[i]>=0)
                ans[vis[i]]++;
        }
        for(int i=0;i<=cc;i++){
            if(ans[i])
                printf("%d %d\n",i,ans[i]);
        }
        cout<<endl;
    }
return 0;
}

说实话,这个代码我是从其他blog上Copy的思想,我原来的代码是WA的,感觉很不爽,但是我又查不出错,我把它放在最下面,希望有大佬能帮我指正!

WA的代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=8001;
int n,le[maxn],ri[maxn],c[maxn],ans,p;
struct Node{
    int col;
}tree[maxn<<2];
void build(int l,int r,int node){
    if(l==r){
        tree[node].col=-1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,node<<1);
    build(mid+1,r,node<<1|1);
    tree[node].col=-1;
}
void push_down(int node){
    if(tree[node].col>=0){
        tree[node<<1].col=tree[node].col;
        tree[node<<1|1].col=tree[node].col;
    }
return;
}
void change(int fl,int fr,int x,int l,int r,int node){
    push_down(node);
    if(fr<l || fl>r || tree[node].col==x)
        return;
    if(fl<=l && fr>=r){
        tree[node].col=x;
        return ;
    }
    int mid=(l+r)>>1;
    change(fl,fr,x,l,mid,node<<1);
    change(fl,fr,x,mid+1,r,node<<1|1);
    if(tree[node<<1].col==tree[node<<1|1].col)
        tree[node].col=tree[node<<1].col;
    else
        tree[node].col=-1;
}
void findx(int l,int r,int node,int aim){
    push_down(node);
    if(tree[node].col<0){
        int mid=(l+r)>>1;
        if(l==r)
            return;
        findx(l,mid,node<<1,aim);
        findx(mid+1,r,node<<1|1,aim);
        if(tree[node<<1].col==tree[node<<1|1].col)
            tree[node].col=tree[node<<1].col;
        else
            tree[node].col=-1;
    }
    else if(tree[node].col==aim){
        if(!p)
            ans++;
        p=1;
        return;
    }
    else{
        p=0;
        return;
    }
}
int main(){
    while (~scanf("%d",&n)){
        int len=0;
        for(int i=1;i<=n;i++){
            scanf("%d %d %d",&le[i],&ri[i],&c[i]);
            len=max(ri[i],len);
        }
        build(1,len,1); 
        for(int i=1;i<=n;i++){
            change(le[i]+1,ri[i],c[i],1,len,1);
        }
        for(int i=0;i<8000;i++){
            ans=0,p=0;
            findx(1,len,1,i);
            if(ans)
                printf("%d %d\n",i,ans);
        }
        cout<<endl;
    }
return 0;
}

和上面的AC代码相比,这个代码就只是改了答案的模式,我觉得利用线段树都是从左扫到右的特点,我对每个颜色进行遍历,ans记录答案,p代表上一个节点是否找到对应的颜色,如果当前节点对应p=1,上个节点不对应,则ans++,反之p=0,ans不变;

我的思路是这样的,但是不知道为什么会WA。。。QAQ

求大佬请教!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值