• 【线段树+离散化】POJ2528-Mayor's posters


    【题目大意】

    在墙上贴海报,问最后能看到几张海报?

    【注意点】

    1.首先要注意这是段线段树,而非点线段树。读题的时候注意观察图。来看discuss区下面这组数据:

    5 6

    4 5

    6 8

    上面数据的答案应该是2,注意观察图,覆盖的是区间。

    2.离散化

    由于覆盖的是区间,不能简单的离散化,否则会出现差错。比如说下面这组数据:

    1 5

    1 3

    4 5

    以及

    1 5

    1 2

    4 5

    如果简单离散化都会变成:

    1 4

    1 2

    3 4

    最后得出只能看到两张海报的结论,而事实上第一组数据中能够看到三张海报,为了解决这个问题,如果相邻两个数之间相差大于1,就补上一个中间的数字。

    比如说1 4,离散化成为1 2 3

    3.数据范围:线段树要开到<<4,至于为什么还没有研究出来。X要开到三倍,因为不仅要考虑左右边界均放进来,而且还要考虑中间增添上来离散化的数字。

     

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define lson l,m,rt<<1
      6 #define rson m+1,r,rt<<1|1
      7 /*define后面绝对不能加分号*/
      8 using namespace std;
      9 const int MAXN=10000+50;
     10 int l[MAXN],r[MAXN];
     11 int X[MAXN*3],t,M;
     12 int col[MAXN<<4];
     13 int hash[MAXN];
     14 /*延迟标记当前区域被编号为几的覆盖*/ 
     15 int ans;
     16 
     17 void pushdown(int rt)
     18 {
     19     if (col[rt]!=-1)
     20     {
     21         col[rt<<1]=col[rt];
     22         col[rt<<1|1]=col[rt];
     23         col[rt]=-1;
     24     }
     25 }
     26 
     27 int Bin(int key)
     28 {
     29     int ub=1,lb=M+1;
     30     while (lb>ub)
     31     {
     32         int m=(ub+lb)/2;
     33         if (X[m]==key) return m;
     34         if (X[m]>key) lb=m;
     35             else (ub=m);
     36     }
     37     return -1;
     38 }
     39 
     40 void update(int L,int R,int l,int r,int rt,int cit)
     41 {
     42     if (L<=l && r<=R) 
     43     {
     44         col[rt]=cit;
     45         return;
     46     }
     47     pushdown(rt);
     48     int m=(l+r)>>1;
     49     if (L <= m) update(L,R,lson,cit);
     50     if (m < R) update(L,R,rson,cit);
     51 }
     52 
     53 void query(int l,int r,int rt)
     54 {
     55     if (col[rt]!=-1)
     56     {
     57         if (hash[col[rt]]!=1) ans++;
     58         hash[col[rt]]=1;
     59         return;
     60     }
     61     if (l==r) return;
     62     int m=(l+r)>>1;
     63     query(lson);
     64     query(rson);
     65 }
     66 
     67 
     68 void init()
     69 /*输入数据并进行离散化*/
     70 {
     71     int num=0;
     72     scanf("%d",&t);
     73     for (int i=0;i<t;i++) 
     74     {
     75         scanf("%d%d",&l[i],&r[i]);
     76         X[++num]=l[i];
     77         X[++num]=r[i];
     78     }
     79     sort(X+1,X+num+1);
     80     /*M来记录离散化之后总共出现了几个数字*/
     81     M=1;
     82     /*注意因为下面的for循环是从2开始的,所以m的初始值要是1,否则第一个数字会被覆盖掉*/
     83     for (int i=2;i<=num;i++)
     84     {
     85         if (X[i]!=X[i-1]) X[++M]=X[i];
     86         /*重复的数字只记录一次*/
     87     }
     88     num=M;
     89     for (int i=2;i<=num;i++)
     90     {
     91         if (X[i]-X[i-1]>1) X[++M]=X[i]-1;
     92         /*离散化时要注意,如果两个点相差大于1,则在中间再插入一个数字*/
     93     }
     94     sort(X+1,X+M+1);
     95 }
     96 
     97 void submain()
     98 {
     99     memset(col,-1,sizeof(col));
    100     for (int i=0;i<t;i++)
    101     {
    102         int lp=Bin(l[i]);
    103         int rp=Bin(r[i]);
    104         update(lp,rp,1,M,1,i);
    105         /*二分查找左边界和右边界离散化后对应的数值*/
    106     }
    107 }
    108 
    109 int main()
    110 {
    111     int T;
    112     scanf("%d",&T);
    113     for (int kase=0;kase<T;kase++) 
    114     {
    115         init();
    116         submain();
    117         ans=0;
    118         memset(hash,0,sizeof(hash));
    119         query(1,M,1);
    120         cout<<ans<<endl;
    121     }
    122     return 0;
    123 }

     

  • 相关阅读:
    UML建模之时序图(Sequence Diagram)
    UML统一建模语UML2和EnterpriseArchitect
    FTP服务器的搭建
    Ubuntu下Apache重启错误:Could not reliably determine解决
    JSP的优势 和劣势 与php的比较
    [置顶] Ajax 初步学习总结
    pv ticketlock解决虚拟环境下的spinlock问题
    Tomcat从零开始(十)Loader
    HDU 4740 The Donkey of Gui Zhou (模拟)
    关于cvScalar的那些事
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5027826.html
Copyright © 2020-2023  润新知