• poj2528 Mayor's posters


    离散化 + 线段树

    坐标按从小到大排序,再构造映射。。

    View Code
    1 //color=0表示未着色或为杂色
    2  
    3 #include <cstdio>
    4 #include <cstring>
    5 #include <algorithm>
    6  using namespace std;
    7
    8 const int MAXN = 40000 + 5;
    9 const int MAX_R = 10000000 + 5;
    10
    11 int n, ans;
    12 bool vis[MAXN] = {};
    13 struct SData{ //记录数据
    14 int b, e;
    15 };
    16 SData data[MAXN];
    17
    18 struct node{ //线段树节点
    19 int l, r;
    20 int color;
    21 };
    22 node tree[MAXN * 3];
    23
    24 struct line{ //s表示端点、num表示该端点是哪个poster的
    25 int s, num;
    26 };
    27 line L[MAXN * 3];
    28
    29 //建树
    30 void build(int i, int ll, int rr){
    31 tree[i].l = ll; tree[i].r = rr;
    32 tree[i].color = 0; //未着色
    33 if(rr != ll){
    34 int mid = (ll + rr) / 2;
    35 build(2*i, ll, mid);
    36 build(2*i+1, mid+1, rr);
    37 }
    38 }
    39
    40 //
    41 void insert(int i, int ll, int rr, int cc){
    42 if(tree[i].l == ll && tree[i].r == rr){
    43 tree[i].color = cc;
    44 return;
    45 }
    46 if(tree[i].r == tree[i].l)
    47 return;
    48
    49 if(tree[i].color > 0 && tree[i].color != cc){
    50 tree[i<<1].color = tree[i].color;
    51 tree[(i<<1)+1].color = tree[i].color;
    52 tree[i].color = 0;
    53 }
    54 int mid = (tree[i].l + tree[i].r) >> 1;
    55 if(rr <= mid)
    56 insert(i<<1, ll, rr, cc);
    57 else if(ll > mid)
    58 insert((i<<1) + 1, ll, rr, cc);
    59 else{
    60 insert(i<<1, ll, mid, cc);
    61 insert((i<<1) + 1, mid+1, rr, cc);
    62 }
    63 }
    64
    65 void sum ( int i )
    66 {
    67 if ( tree[i].color )
    68 {
    69 if ( !vis[tree[i].color] )
    70 {
    71 vis[tree[i].color]=true;
    72 ans++;
    73 }
    74 return;
    75 }
    76 sum( i<<1 );
    77 sum( (i<<1)+1 );
    78 }
    79
    80 bool cmp(line a, line b){
    81 return a.s < b.s;
    82 }
    83
    84 int main(){
    85 int c;
    86 scanf("%d", &c);
    87 while(c--){
    88 scanf("%d", &n);
    89
    90 for(int i=0; i<n; i++){
    91 scanf("%d%d", &data[i].b, &data[i].e);
    92
    93 L[2*i].s = data[i].b; L[2*i].num=-(i+1); //负数表示是poster的左端点
    94 L[2*i+1].s = data[i].e; L[2*i+1].num=i+1; //正数表示是右端点
    95 }
    96   
    97
    98 //离散化……
    99 sort(L, L+2*n, cmp);
    100 int cnt=1, temp = L[0].s;
    101 for(int i=0; i<2*n; i++){
    102 if(L[i].s != temp){
    103 cnt++;
    104 temp=L[i].s;
    105 }
    106 if(L[i].num < 0) //如果是左端点
    107 data[-L[i].num-1].b = cnt;
    108 else //如果是右端点
    109 data[L[i].num-1].e = cnt;
    110 }
    111
    112
    113 //线段树……
    114 build(1, 1, cnt);
    115
    116 for(int i=0; i<n; i++){
    117 insert(1, data[i].b, data[i].e, i+1);
    118 }
    119
    120
    121 memset(vis, 0, sizeof(vis));
    122 ans = 0;
    123 sum(1);
    124
    125 printf("%d\n", ans);
    126
    127 }
    128
    129
    130 return 0;
    131 }

    另附:

    【转】

    关于这个题离散化的问题,在discuss里有人说测试数据是错的,如果按照一般的离散化的方法去写有种数据不能过

    1 10

    1 5

    8 10

    如果像我下面的代码那样写离散化的结果

    1 4

    1 2

    3 4

    很明显6-7这条线段在离散化时被消除了

    如果想得到正确的结果其实只用在离散化时修改一下就可以了。

    如果这两条线段的两个端点是相邻的,cnt++

    不相邻cnt+=2;

    正确的离散化代码:

    View Code
    1 for(i=1;i<2*n;i++)
    2 {
    3 if(L[i].s!=L[i-1].s)
    4 {
    5 if(L[i-1].s+1==L[i].s)
    6 cnt+=1;
    7 else
    8 cnt+=2;
    9 }
    10 if(L[i].flag)
    11 p[L[i].num].x=cnt;
    12 else
    13 p[L[i].num].y=cnt;
    14 }
  • 相关阅读:
    git push 报错:missing Change-Id in commit message footer
    script命令录屏
    dubbo.xsd
    常规项目用到的jar包之maven的pom.xml
    WebSocket Demo
    对程序员有帮助的站点集锦
    java之finally的用法
    Java 中的四种引用
    字符串类型的对象与引用及字符串常量池详解
    如何掌握一项新的技能?
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2102271.html
Copyright © 2020-2023  润新知