ZOJ_1610_思维+线段树

zoj 1610

  1. 思维:
  • 线段区间[1,8000],颜色区间[0,8000]
  • 记录输入.找每个点的最后一个覆盖点就行了
  • 然后算多少个颜色段
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #include <iostream>
    #include <string.h>

    using namespace std;
    const int maxn = 1e4;
    int n;
    int e[maxn][3];
    int color[maxn];
    int ans[maxn];
    int main() {
    // freopen("a.txt","r",stdin);
    while (scanf("%d",&n) != EOF) {
    memset(ans,0,sizeof ans);
    memset(color,-1,sizeof color);

    for (int i=1; i<=n; i++) {
    scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
    e[i][0]++;
    }
    for (int i=1; i<=8000; i++) //遍历每一个位置,找到最后一次覆盖这个位置的值
    for (int j=n; j>=1; j--)
    if (e[j][0]<=i && i<=e[j][1]) {
    color[i] = e[j][2];
    break;
    }
    // 现在统计所有颜色段的值 都统计出来
    // for(int i=1; i<=right; i++) printf("%d ",color[i]);
    int last = -99;
    for (int i=1; i<=8000; i++) {
    if (last == color[i]) continue;
    else {
    last = color[i];
    ans[color[i]]++;
    }
    }
    for (int i=0; i<= 8000; i++) {
    if (ans[i]) printf("%d %d\n",i,ans[i]);
    }
    printf("\n");
    }
    return 0;
    }

2.线段树

  • add() == -1因为颜色可能为0
  • 线段树区间修改模板求出最后的所有点的颜色
  • 统计颜色段
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include <iostream>
    #include <string.h>
    using namespace std;
    const int maxn = 8010;
    struct segementTree {
    int left,right;
    int add;
    #define left(x) tree[x].left
    #define right(x) tree[x].right
    #define add(x) tree[x].add
    }tree[maxn*4];
    int color[maxn];
    int ans[maxn];
    void build(int p,int left,int right) {
    right(p) = right; left(p) = left;
    add(p) = -1; // 颜色可能是0,
    if (left == right) return;
    int mid = (left + right)/2;
    build(2*p,left,mid);
    build(2*p+1,mid+1,right);
    }
    void pushDown(int p) {
    if (add(p) != -1) {
    add(2*p) = add(2*p+1) = add(p);
    add(p) = -1;
    }
    }
    void change(int p,int left,int right,int val) {
    if (left<=left(p) && right(p)<=right) {
    add(p) = val;
    return ;
    }
    pushDown(p);
    int mid = (left(p) + right(p))/2;
    if (left <= mid) change(2*p,left,right,val);
    if (mid < right) change(2*p+1,left,right,val);
    }
    void ask(int p,int left,int right) {
    if (left(p) == right(p)) {
    color[left(p)] = add(p);
    return ;
    }
    pushDown(p);
    int mid = (left(p) + right(p))/2;
    if (left <= mid) ask(2*p,left,right);
    if (mid < right) ask(2*p+1,left,right);
    }
    int main() {
    // freopen("a.txt","r",stdin);
    int n;
    while (scanf("%d",&n) != EOF) {
    memset(color,0,sizeof color);
    memset(ans,0,sizeof ans);
    build(1,1,8000);
    int u,v,w;
    for(int i=1; i<=n; i++) {
    scanf("%d%d%d",&u,&v,&w);
    u++;
    // printf("%d %d\n",u,v);
    change(1,u,v,w);
    }
    ask(1,1,8000);
    // 区间段的颜色已经维护出来
    int last = -99;
    for (int i=1; i<=8000; i++) {
    if (last == color[i]) continue;
    else {
    last = color[i];
    ans[color[i]]++;
    }
    }
    for (int i=0; i<= 8000; i++) {
    if (ans[i]) printf("%d %d\n",i,ans[i]);
    }
    printf("\n");
    }
    return 0;
    }

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!