标签:
题意:
求每种颜色有几段线段;
模拟数组:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; #define N 8006 int cnt[N],a[N]; int main() { int n, p, q, c; while(scanf("%d", &n) != EOF) { int Max = 0; memset(a, 0, sizeof(a)); memset(cnt, 0, sizeof(cnt)); for(int i=0; i<n; i++) { scanf("%d%d%d", &p, &q, &c); for(int j=p; j<q; j++) a[j] = c+1; Max = max(Max, q); } for(int i=0; i<Max; i++) { while(i!=0 && a[i]!=0 && a[i]==a[i-1]) i++; if(a[i] != 0) cnt[ a[i]-1 ]++; } for(int i=0; i<N; i++) { if(cnt[i]!=0) printf("%d %d\n", i, cnt[i]); } printf("\n"); } return 0; }
#include<stdio.h> #include<string.h> #define N 8005 struct SegTree { int L,R,c; int mid() { return (L+R)>>1; } }a[N*4]; int cnt[N], vis[N]; void BuildSegTree(int r, int L, int R) { a[r].L = L; a[r].R = R; a[r].c = -1; if(L+1==R)//一条线段的两个端点相差1, return ; BuildSegTree(r*2, L, a[r].mid()); BuildSegTree(r*2+1, a[r].mid(), R);//题目给的是端点值,对于线段不能用a[r].mid()+1; } void Update(int r, int L, int R, int c) { if(a[r].c == c)return ;//如果说这条线段的颜色和要涂的相同,返回; if(a[r].L == L && a[r].R == R) { a[r].c = c;//指定范围内改成颜色c; return ; } if(a[r].c != -1) { a[2*r].c = a[2*r+1].c = a[r].c;//更新左右子树; a[r].c = -1; } if(R<=a[r].mid()) Update(2*r, L, R, c); else if(L>=a[r].mid())//等于号不能省;原因是这是线段不是点; Update(2*r+1, L, R, c); else { Update(2*r, L, a[r].mid(), c); Update(2*r+1, a[r].mid(), R, c); } } void Query(int r, int L, int R) { if(a[r].c != -1)//到达叶子节点; { if(vis[L] != a[r].c) cnt[ a[r].c ]++; vis[R] = a[r].c; return ; } if(R-L == 1) return ; Query(2*r, L, a[r].mid()); Query(2*r+1, a[r].mid(), R); } int main() { int n, p, q, c; while(scanf("%d", &n) != EOF) { memset(cnt, 0, sizeof(cnt)); memset(vis, -1, sizeof(vis)); BuildSegTree(1, 0, 8000); while(n--) { scanf("%d %d %d", &p, &q, &c); if(p == q)continue; Update(1, p, q, c); } Query(1, 0, 8000); for(int i=0; i<N; i++) { if(cnt[i] != 0) printf("%d %d\n", i, cnt[i]); } printf("\n"); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zhengguiping--9876/p/4692806.html