POJ2528Mayor's posters 线段树,离散化技巧

  • 题意:一个坐标轴从1~1e7,每次覆盖一个区间(li,ri),问最后可见区间有多少个(没有被其他区间挡住的)
  • 线段树,按倒序考虑,贴上的地方记为1,每次看(li,ri)这个区间是否全是1,全是1就说明在它后面贴的把它给挡住了,否则该海报可见。
  • 然后就愉快的MLE了。。。。
  • 再看看数据范围,离散化如下,比如如果海报的左右端点如下
  • 那图中橙色的一块的大小其实对结果没有影响,可以把他们都缩为1

  • 最后离散化结果如下图:

  • 代码:

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdio>
     4 #define nmax 10010
     5 #define tn t[node]
     6 #define sl (node<<1)
     7 #define sr (1+(node<<1))
     8
     9 using namespace std;
    10 int n;
    11 int inl[nmax],inr[nmax];
    12 struct tin{
    13     int pd,id,num,n2; //0 ->l  1->r
    14     bool operator < (const tin x) const { return x.num>num; }
    15 }in[nmax*2];
    16 struct segt { int l,r,v; }t[nmax*15];
    17
    18 void build(int node,int l,int r){
    19     tn.l=l;
    20     tn.r=r;
    21     tn.v=0;
    22     if(l==r) return;
    23     int mid=(l+r)>>1;
    24     build(sl,l,mid);
    25     build(sr,mid+1,r);
    26 }
    27
    28 int upd(int l,int r,int node,int tv){
    29     int ta=(tv||tn.v);
    30     if(tn.l>=l&&tn.r<=r) tn.v=1;
    31     else{
    32         int mid=(tn.l+tn.r)>>1;
    33         int tl=1,tr=1;
    34         if(l<=mid) tl=upd(l,r,sl,tv||tn.v);
    35         if(r>mid) tr=upd(l,r,sr,tv||tn.v);
    36         ta=(tl&&tr)||tv;
    37         tn.v=tn.v||(t[sl].v&&t[sr].v);
    38     }
    39     return ta;
    40 }
    41
    42 int main(){
    43     int cas;
    44     cin>>cas;
    45     while(cas--){
    46         cin>>n;
    47         for (int i=0; i<n; i++) {
    48             scanf("%d%d",&in[i].num,&in[i+n].num);
    49             in[i].pd=0;
    50             in[i+n].pd=1;
    51             in[i].id=in[i+n].id=i;
    52         }
    53         sort(in,in+2*n);
    54         //离散化
    55         int w=0;
    56         in[0].n2=(++w);
    57         for (int i=1; i<2*n; i++) {
    58             if(in[i].num==in[i-1].num ) {
    59                 in[i].n2=w;
    60                 continue;
    61             }
    62             in[i].n2=(++w);
    63             if( in[i].num!=in[i-1].num+1 ) in[i].n2=(++w);
    64         }
    65         //离散化over
    66         build(1,1,w);
    67         for (int i=0; i<2*n; i++) if(in[i].pd) inr[in[i].id]=in[i].n2; else inl[in[i].id]=in[i].n2;
    68         int ans=0;
    69         for (int i=n-1; i>=0; i--) if(upd(inl[i],inr[i],1,0)==0) ans++;
    70         printf("%d\n",ans);
    71     }
    72     return 0;
    73 }

POJ2528Mayor's posters 线段树,离散化技巧

原文地址:https://www.cnblogs.com/jiecaoer/p/11604248.html

时间: 2024-11-09 09:30:34

POJ2528Mayor's posters 线段树,离散化技巧的相关文章

poj2528--Mayor&#39;s posters(线段树+离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 41785   Accepted: 12164 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

POJ2528Mayor&#39;s posters[线段树 离散化]

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 59683   Accepted: 17296 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

Poj2528Mayor&#39;s posters线段树

先贴,明天再补. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #inclu

POJ--2528--Mayor&#39;s posters【线段树+离散化】

题意:在一块木板上贴海报,每次贴海报给一个横坐标范围,在这个范围内贴,按照它给的顺序,海报可以被覆盖,问最后还能看见几张海报. 都说这是线段树入门题....结果我还是出翔了,不是在线段树部分,是在离散化部分. 我之前看到一个很飘逸的离散化写法,可惜找不到了,这回是这么写的:去重之后再把每个点的后一个值也加入离散化后的数组(如果这个值之前没有的话),这样避免了漏掉中间没被覆盖的情况. 然后样例都没调通,后来发现lowwer_bound返回值有可能是0,而我的线段树是以1为左边界的,每次这么更新难免

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

线段树+离散化 POJ 2528 Mayor&#39;s posters

题目传送门 题意:在一面墙上贴海报,有先后顺序,问最后有多少张不同的海报(指的是没被覆盖或者只是部分覆盖的海报) 分析:这题数据范围很大,直接搞超时+超内存,需要离散化:离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来

POJ - 2528 - Mayor&#39;s posters 【线段树+离散化+补点】

http://poj.org/problem?id=2528 #include <cstdio> #include <iostream> #include <set> #include <cstring> #include <string> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 32768 + 5; in

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9