• poj2528 (线段树+离散化)


    传送门::http://poj.org/problem?id=2528

    题意: 在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报

    数据:1 <= i <= n, 1 <= li <= ri <= 10000000;1 <= n <= 10000

    思路:离散化+线段树

    离散化 定义::把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。(by百度百科)

     通俗点说就是 在不改变数据的可用性质下缩小其范围,一般只关注他们的相对大小

    但对于本题而言普通离散化不行,我们还要维护一个性质,那就是是否相邻,举个例子就会明白

    [1,5] [1,2] [4,5]离散后[1,4] [1,2][3,4]这样做的答案为2(原因就是二三区间归为一起,导致覆盖第一区间),而实际上答案为3

    那我们应该在差值大于1的两个数之间插入一个数,避免相邻的归为一个区间

    所以  离散化两性质:大小关系和是否相邻

    线段树:

    只需开一个数组来标记出现过的颜色即可

     1 //#include<bits/stdc++.h>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<string.h>
     5 #include<string>
     6 #include<iostream>
     7 #define ll long long
     8 const int maxn=1e5+5;
     9 using namespace std;
    10 
    11 int a[maxn],b[maxn],c[maxn*2];
    12 int lazy[maxn<<2];
    13 bool use[maxn<<2];
    14 int ans;
    15 
    16 void pushdown(int rt)
    17 {
    18     if(lazy[rt]){
    19         lazy[2*rt]=lazy[2*rt+1]=lazy[rt];
    20         lazy[rt]=0;
    21     }
    22 }
    23 void update(int L,int R,int l,int r,int rt,int add)
    24 {
    25     if(L<=l&&R>=r){
    26         lazy[rt]=add;
    27         return ;
    28     }
    29     int mid=(l+r)>>1;
    30     pushdown(rt);
    31     if(L<=mid){
    32         update(L,R,l,mid,2*rt,add);
    33     }
    34     if(R>mid){
    35         update(L,R,mid+1,r,2*rt+1,add);
    36     }
    37 }
    38 void query(int L,int R ,int l,int r,int rt)
    39 {
    40     if(lazy[rt]!=0){
    41         if(!use[lazy[rt]])ans++;
    42         use[lazy[rt]]=1;
    43         return ;
    44     }
    45     if(l==r){return ;}
    46     int mid=(l+r)>>1;
    47     if(L<=mid){
    48         query(L,R,l,mid,2*rt);
    49     }
    50     if(R>mid){
    51         query(L,R,mid+1,r,2*rt+1);
    52     }
    53 }
    54 int main()
    55 {
    56     int t,k,m;
    57     scanf("%d",&t);
    58     while(t--){
    59     m=ans=0;
    60     memset(use,0,sizeof(use));
    61     memset(lazy,0,sizeof(lazy));
    62     scanf("%d",&k);
    63     for(int i=1;i<=k;i++)
    64     {
    65         scanf("%d%d",&a[i],&b[i]);
    66         c[++m]=a[i];c[++m]=b[i];
    67     }
    68     sort(c+1,c+m+1);
    69     m=unique(c+1,c+m+1)-c;
    70     m--;
    71     for(int i=m;i>1;i--)
    72     {
    73         if(c[i]-1>c[i-1]){
    74             c[++m]=c[i-1]+1;
    75         }
    76     }
    77     sort(c+1,c+m+1);
    78     m=unique(c+1,c+m+1)-c;
    79     for(int i=1;i<=k;i++){
    80         a[i]=lower_bound(c+1,c+m,a[i])-c;
    81         b[i]=lower_bound(c+1,c+m,b[i])-c;
    82         update(a[i],b[i],1,m-1,1,i);
    83     }
    84     query(1,m-1,1,m-1,1);
    85     cout<<ans<<endl;
    86     }
    87     return 0;
    88 }
    View Code
    纵使单枪匹马,也要勇闯天涯
  • 相关阅读:
    MySQL根据某一个或者多个字段查找重复数据的sql语句
    常见面试题
    技术总监工作内容
    分布式锁三种实现
    完美解决github访问速度慢
    细说Redis
    Mysql学习的核心问题
    Java反射细说
    Spring中的常见的9种设计模式
    Mybatis相关问题
  • 原文地址:https://www.cnblogs.com/sj-gank/p/11779291.html
Copyright © 2020-2023  润新知