zoukankan      html  css  js  c++  java
  • poj2528线段树解题报告,离散化+线段树

    题目网址:http://poj.org/problem?id=2528

    题意:

      n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。

          求出最后还能看见多少张海报。

      输入:

     1
     5
     1 4
     2 6
     8 10
     3 4
     7 10
     这题用常规思路解题必定TLE,l,r太大;

    通俗点说,离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:

    有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。

    现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9

    然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9

    对其升序排序,得2 3 4 6 8 9 10

    然后建立映射

    2     3     4     6     8     9   10

    ↓     ↓      ↓     ↓     ↓     ↓     ↓

    1     2     3     4     5     6     7

    那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。

    离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <algorithm>
      4 #include <string.h>
      5 using namespace std;
      6 #define  N  10100
      7 #define    M 10000000
      8 bool vis[2*N];//标记出现过得海报
      9 int x[2*N];
     10 struct T
     11 {
     12      int node,add,l,r;
     13 }tree[M*4];
     14 void creat(int l,int r,int k)//建树
     15 {
     16      tree[k].node=0;
     17      tree[k].l=l;
     18      tree[k].r=r;
     19      tree[k].add=0;
     20      if(l==r)
     21          return;
     22      int mid=(l+r)>>1;
     23      creat(l,mid,k<<1);
     24      creat(mid+1,r,k<<1|1);
     25 }
     26 void pushdown(int k,int color)//延迟标记
     27 {
     28      int x=k<<1;
     29      tree[x].add=1;
     30      tree[x+1].add=1;
     31      tree[x].node=color;
     32      tree[x+1].node=color;
     33      tree[k].add=0;
     34      tree[k].node=0;
     35 }
     36 void Search(int l,int r,int color,int k)//更新线段树
     37 {
     38      if(r<tree[k].l||l>tree[k].r)
     39          return ;
     40      if(l<=tree[k].l&&r>=tree[k].r)
     41      {
     42          tree[k].node=color;
     43          tree[k].add=1;
     44          return ;
     45      }
     46      if(tree[k].add)
     47          pushdown(k,tree[k].node);
     48      int mid=(tree[k].l+tree[k].r)>>1;
     49      if(r<=mid)
     50          Search(l,r,color,k<<1);
     51      else if(l>mid)
     52           Search(l,r,color,k<<1|1);
     53         else
     54         {
     55              Search(l,mid,color,k<<1);
     56              Search(mid+1,r,color,k<<1|1);
     57         }
     58 }
     59 int ans;
     60 void q(int l,int r,int k)//查找不同颜色的区域
     61 {
     62      if(tree[k].add)
     63      {
     64          if(!vis[tree[k].node])
     65         {
     66           ans++;
     67           vis[tree[k].node]=1;
     68          }
     69          return ;
     70      }
     71      int mid=(l+r)>>1;
     72      q(l,mid,k<<1);
     73      q(mid+1,r,k<<1|1);
     74 }
     75 int s(int l,int r,int k)//二分查找
     76 {
     77     int mid;
     78      while(l<=r)
     79      {
     80          mid=(l+r)>>1;
     81          if(k<x[mid]) r=mid-1;
     82          else if(k>x[mid]) l=mid+1;
     83          else return mid;
     84      }
     85      return -1;
     86 }
     87 int main()
     88 {
     89     int t,n,i,j;
     90     int l[N],r[N];
     91    scanf("%d",&t);
     92     while(t--)
     93     {
     94          j=0;
     95          memset(vis,0,sizeof(vis));
     96          scanf("%d",&n);
     97          for(i=0;i<n;i++)
     98          {
     99              scanf("%d%d",&l[i],&r[i]);
    100              x[j++]=l[i];
    101              x[j++]=r[i];
    102          }
    103          sort(x,x+j);
    104          int m=1;
    105          for(i=0;i<j-1;i++)
    106          {
    107              if(x[i]==x[i+1])
    108             {
    109                  m--;
    110             }
    111             else
    112             {
    113                  x[i+m]=x[i+1];
    114             }
    115          }
    116          j=j+m-1;
    117          sort (x,x+j);
    118          /*for(i=0;i<n;i++)
    119          {
    120              printf("%d %d ",s(0,j-1,l[i])+1,s(0,j-1,r[i])+1);
    121              cout<<endl;
    122          }*/
    123         creat(1,j,1);
    124          for(i=0;i<n;i++)
    125          {
    126              Search(s(0,j-1,l[i])+1,s(0,j-1,r[i])+1,i+1,1);
    127          }
    128          ans=0;
    129        q(1,j,1);
    130          printf("%d
    ",ans);
    131     }
    132     return 0;
    133 }

     

  • 相关阅读:
    Python 文件去重(转载)
    Mongodb 3.6.5 Compass可视化工具的使用
    mongodb启动错误(Failed to set up listener: SocketException: Cannot assign requested address)
    MongDB 配置参数设置
    MongDB 配置参数查看
    Python 可视化篇:流式数据监控(转载)
    CentOS7 5 ansible playbook 示例
    CentOS7 3 模块介绍 ansible
    CentOS7 2 配置 ansible
    Linux下离线安装python项目的依赖包 (转载)
  • 原文地址:https://www.cnblogs.com/yuanbo123/p/5511254.html
Copyright © 2011-2022 走看看