ZOJ 1610 Count the Colors 【线段树】
<题目链接>
题目大意:
在[0,8000]这个区间内,不断进行一些操作,将其中的一些区间染成特定颜色,如果区间重复的话,后面染的色块会覆盖前面染的色块,问最终[0,8000]这个区间内每种颜色的色块数量是多少。
解题分析:
首先要注意,这是对区间进行更新,。所以update的时候是对输入区间[a,b]的左闭右开或者是左开右闭进行处理。然后本题思路非常清晰,就是按照输入顺序更新线段树对应区间,然后对[0,8000]这个区间从左向右进行色块的统计。PS:虽然最后还是要将所有lazy下放到所有的叶子节点,进行色块数量的暴力统计,但是pushdown函数确实能够减少 update 的一些复杂度。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 #define Lson rt<<1,l,mid 7 #define Rson rt<<1|1,mid+1,r 8 const int M =8e3; 9 int tr[M<<2],lazy[M<<2],last; 10 int col[M<<1]; 11 void Pushdown(int rt){ 12 if(lazy[rt]!=-1){ 13 int tmp=lazy[rt]; 14 lazy[rt<<1]=lazy[rt<<1|1]=tmp; 15 tr[rt<<1]=tr[rt<<1|1]=tmp; 16 lazy[rt]=-1; 17 } 18 } 19 void update(int rt,int l,int r,int L,int R,int c){ //区间染色 20 if(L<=l&&r<=R){ 21 lazy[rt]=c; 22 tr[rt]=c; 23 return; 24 } 25 Pushdown(rt); 26 int mid=(l+r)>>1; 27 if(L<=mid)update(Lson,L,R,c); 28 if(R>mid)update(Rson,L,R,c); 29 } 30 void query(int rt,int l,int r){ //运用递归(类似于dfs),达到从左到右逐步查询的效果,当遇到染色的点时,判断其是否与前一个点相同,如果不同,就说明该颜色的区块 31 if(l==r){ 32 if(tr[rt]!=last&&tr[rt]!=-1)col[tr[rt]]++; 33 last=tr[rt]; 34 return; 35 } 36 Pushdown(rt); 37 int mid=(l+r)>>1; 38 query(Lson); 39 query(Rson); 40 } 41 int main(){ 42 int n; 43 while(scanf("%d",&n)!=EOF){ 44 memset(tr,-1,sizeof(tr)); 45 memset(lazy,-1,sizeof(lazy)); 46 memset(col,0,sizeof(col)); 47 while(n--){ 48 int x,y,c; 49 scanf("%d%d%d",&x,&y,&c); 50 update(1,1,M,x+1,y,c); //由于本题是区间更新,所以不能直接更新[a,b]这个闭区间的所有点,而是对a~b的左开右闭或者左闭右开区间进行更新,类似于图的将边权转化为点权 51 } 52 last=-1; 53 query(1,1,M); 54 for(int i=0;i<=M;i++){ 55 if(col[i])printf("%d %d\n",i,col[i]); 56 } 57 printf("\n"); 58 } 59 return 0; 60 }
2018-09-22
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。