ZOJ 1610 Count the Colors (线段树 成段更新)
题意:成段染色,初始为0,每次改变一个区间的颜色,求最后每种颜色分别有多少段。颜色按照从
小到大输出。
分析:改变了代码的风格,因为看了学长的博客。直接用数组,可以只是记录节点的编号,因为节点编号
确定了,则l,r也就确定了。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #define LL __int64 8 #define lson l, mid, 2*rt 9 #define rson mid+1, r, 2*rt+1 10 const int maxn = 8000+10; 11 using namespace std; 12 int val[4*maxn], num[maxn]; 13 14 void pushdown(int rt) //如果没有更新,向下更新 15 { 16 if(val[rt]!=-1) 17 { 18 val[2*rt] = val[rt]; 19 val[2*rt+1] = val[rt]; 20 val[rt] = -1; 21 } 22 } 23 void update(int ll, int rr, int c, int l, int r, int rt) //ll,rr代表要找的区间,不用减小了,一直都是这个 24 { 25 if(ll<=l && rr>=r) //如果当前节点的范围在 改变的节点的范围内就 改变 26 { 27 val[rt] = c; 28 return; 29 } 30 pushdown(rt); 31 int mid = (l+r)/2; 32 if(ll<=mid) update(ll, rr, c, lson); //看这个左半区间内是否还有点 33 if(rr>mid) update(ll, rr, c, rson); 34 } 35 int query(int p, int l, int r, int rt) 36 { 37 if(l>p) return 0; 38 if(r<p) return 0; 39 if(p==l&&p==r) return val[rt]; 40 if(p>=l && p<=r && val[rt]!=-1) return val[rt]; 41 int mid = (l+r)/2; 42 return query(p, lson)+query(p, rson); 43 } 44 int main() 45 { 46 int i, n, l, r, c, x, pre; 47 while(~scanf("%d", &n)) 48 { 49 memset(val, -1, sizeof(val)); //相当于建树 50 memset(num, 0, sizeof(num)); 51 while(n--) 52 { 53 scanf("%d%d%d", &l, &r, &c); 54 if(r-1 >= l) 55 update(l, r-1, c, 0, 8000, 1); 56 } 57 pre = -1; 58 for(i = 0; i <= 8000; i++) //查询的是区间00,11.。。 59 { 60 x = query(i, 0, 8000, 1); 61 if(x!=pre) //如果不连续 就加上 62 { 63 pre = x; 64 if(x>=0) num[x]++; 65 } 66 } 67 for(i = 0; i <= 8000; i++) 68 { 69 if(num[i]) 70 printf("%d %d\n", i, num[i]); 71 } 72 printf("\n"); 73 } 74 return 0; 75 }