ZOJ 1610 线段树

来源:互联网 发布:电脑群发短信的软件 编辑:程序博客网 时间:2024/05/18 16:39

题意

N次涂颜料,第I次涂x1到x2区间,涂颜色C。问最后能看见多少种颜色,以及这些颜色的连续块个数。

题解

单点查询,多点更新的线段树。由于数据范围只有0-8000,所以也不用做什么处理,随便搞搞就可以了。

注意事项

题目都错了然后就各种SF和WA。。。题目的意思是涂N次颜料,每次区间都在0-8000之间,而不是0-N之间。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define INF 0x3f3f3f3f#define LL long long#define MAXN 100010#define EPS 1e-10#define MOD 100000000using namespace std;int lt,rt,v;int setv[MAXN];int num[MAXN];int color[MAXN];void pushdown(int o){    if(setv[o]>=0){        setv[o*2+1]=setv[o*2]=setv[o];    }    setv[o]=-1;}void update(int o,int l,int r){    if(lt<=l&&rt>=r){        setv[o]=v;    }else{        pushdown(o);        int m=l+(r-l)/2;        if(lt<=m){            update(o*2,l,m);        }        if(rt>m){            update(o*2+1,m+1,r);        }    }}int query(int o,int l,int r){    if(setv[o]>=0){        return setv[o];    }else if(lt<=l&&rt>=r){        return num[o];    }else{        int m=l+(r-l)/2;        if(lt<=m){            return query(o*2,l,m);        }        if(rt>m){            return query(o*2+1,m+1,r);        }    }}int main(){    int n;    W(~scanf("%d",&n)){        MEM(color,0);        MEM(num,-1);        MEM(setv,-1);        UP(i,0,n){            scanf("%d%d%d",&lt,&rt,&v);            lt++;            if(lt>rt)                continue;            update(1,1,8010);        }        int last=-1;        UP(i,1,8010){            lt=i,rt=i;            int x=query(1,1,8010);            if(x!=last){                last=x;                if(x>=0)                    color[x]++;            }        }        UP(i,0,8010){            if(color[i]>0)                printf("%d %d\n",i,color[i]);        }        puts("");    }}
原创粉丝点击