zoukankan      html  css  js  c++  java
  • 影子的宽度&&盒子的个数

    影子的宽度

    问题描述

    桌子上零散地放着若干个盒子,盒子都平行于墙。桌子的后方是一堵墙。如图所示。现在从桌子的前方射来一束平行光, 把盒子的影子投射到了墙上。问影子的总宽度是多少?

    enter image description here

    输入格式

    第1行:3个整数L,R,N。-100000 ≤L≤R≤ 100000,表示墙所在的区间;1≤N≤100000,表示盒子的个数 接下来N行,每行2个整数BL, BR,-100000 ≤BL≤BR≤ 100000,表示一个盒子的左、右端点

    输出格式

    第1行:1个整数W,表示影子的总宽度。

    样例输入

    Sample Input 1

    0 7 2

    1 2

    4 5

    Sample Input 2

    -10 10 2

    -5 2

    -2 2

    Sample Input 3

    -10 10 3

    -7 0

    -4 9

    -4 2

    Sample Input 4

    -100 100 3

    -7 2

    5 9

    2 5

    Sample Input 5

    -50 50 4

    -2 4

    0 6

    9 10

    -5 30

    样例输出

    Sample Output 1

    2

    Sample Output 2

    7

    Sample Output 3

    16

    Sample Output 4

    16

    Sample Output 5

    35

    题解

    用线段树维护左闭右开的区间 [l,r)影子的总宽度,标记flag表示这段区间是否全被影子覆盖。下传标记的时候,传完后不能置为0。

     1 #include <cstdio>
     2 const int maxn=100000;
     3 struct node{
     4     int num;
     5     bool lb,rb,flag;
     6 }f[5000005];
     7 int n,L,R,s,t;
     8 int max(int x,int y)
     9 {
    10     return x>y?x:y;
    11 }
    12 void pushdown(int l,int r,int id)
    13 {
    14     if (!f[id].flag) return;
    15     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
    16     f[ls].num=mid-l;
    17     f[rs].num=r-mid;
    18     f[ls].flag=f[rs].flag=1;
    19     f[ls].lb=f[ls].rb=f[rs].lb=f[rs].rb=1;
    20 //    f[id].flag=0;      // 不知道为什么写了这句会WA 
    21     return;
    22 }
    23 void modify(int l,int r,int id)  //  [ l , r )
    24 {
    25     pushdown(l,r,id);
    26     if (s<=l && r<=t)
    27     {
    28         f[id].num=r-l;
    29         f[id].lb=f[id].rb=1;
    30         f[id].flag=1;
    31         return;
    32     }
    33     f[id].flag=0;
    34     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
    35     if (s<mid) modify(l,mid,ls);  // 注意!!!由于是左闭右开区间,这里没有等号 
    36     if (t>mid) modify(mid,r,rs);
    37     f[id].lb=f[ls].lb;
    38     f[id].rb=f[rs].rb;
    39     f[id].num=f[ls].num+f[rs].num;
    40 //    pushdown(l,mid,ls);
    41 //    pushdown(mid,r,rs);
    42     return;
    43 }
    44 int main()
    45 {
    46     int i,j;
    47     scanf("%d%d%d",&L,&R,&n);
    48     L+=maxn;  R+=maxn;
    49     while (n--)
    50     {
    51       scanf("%d%d",&s,&t);      
    52       s+=maxn,t+=maxn;
    53       modify(L,R,1);
    54     }      
    55     printf("%d",f[1].num);
    56     return 0;
    57 }

    盒子的个数

    问题描述

    桌子上零散地放着若干个盒子,盒子都平行于墙。桌子的后方是一堵墙。如图所示。问从桌子前方可以看到多少个盒子?假设人站得足够远。 enter image description here

    输入格式

    第1行:3个整数L,R,N。-100000 ≤L≤R≤ 100000,表示墙所在的区间;1≤N≤100000,表示盒子的个数 接下来N行,每行2个整数BL, BR,-100000 ≤BL≤BR≤ 100000,表示一个盒子的左、右端点。越在前面输入的盒子越排在离墙近的位置,后输入的盒子排在离墙远的位置。

    输出格式

    第1行:1个整数M,表示可看到的盒子个数。

    样例输入

    1 10 5

    2 6

    3 6

    4 6

    1 2

    3 6

    样例输出

    3

    题解

    做出前面那题,这题就比较简单了。

    易得,一个离墙最远的盒子不会被其它盒子挡住。由此可推,对于任意一个盒子i,设它到墙的距离为d[i],如果所有d[j]>d[i]的盒子j不能把盒子i完全挡住,那么盒子i就可以被看到。

    回忆前一题,每添加一个盒子,就会把线段树的一些区间完全覆盖,那么我们倒过来,从n到1添加盒子,在添加第i个盒子前,线段树上被覆盖的区间就是被挡住看不到的区间。要判断一个盒子能不能被看到,只要在这个盒子覆盖区间之前,判断一下要被覆盖的区间是不是已经被完全覆盖,如果没有被完全覆盖,这个盒子就可以被看到。

     1 #include <cstdio>
     2 const int maxn=100000;
     3 struct node{
     4     int num;
     5     bool lb,rb,flag;
     6 }f[5000005];
     7 int n,L,R,s,t,bl[100005],br[100005],ans,p;
     8 bool cansee[100005];
     9 int max(int x,int y)
    10 {
    11     return x>y?x:y;
    12 }
    13 void pushdown(int l,int r,int id)
    14 {
    15     if (!f[id].flag) return;
    16     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
    17     f[ls].num=mid-l;
    18     f[rs].num=r-mid;
    19     f[ls].flag=f[rs].flag=1;
    20     f[ls].lb=f[ls].rb=f[rs].lb=f[rs].rb=1;
    21     return;
    22 }
    23 void modify(int l,int r,int id)  //  [ l , r )
    24 {    
    25     pushdown(l,r,id);
    26     if (s<=l && r<=t)
    27     {
    28         if (f[id].num<r-l) cansee[p]=1;
    29         f[id].num=r-l;
    30         f[id].lb=f[id].rb=1;
    31         f[id].flag=1;
    32         return;
    33     }
    34     f[id].flag=0;
    35     int ls=id<<1,rs=ls|1,mid=(l+r)>>1;
    36     if (s<mid) modify(l,mid,ls);
    37     if (t>mid) modify(mid,r,rs);
    38     f[id].lb=f[ls].lb;
    39     f[id].rb=f[rs].rb;
    40     f[id].num=f[ls].num+f[rs].num;
    41     return;
    42 }
    43 int main()
    44 {
    45     int i,j;
    46     scanf("%d%d%d",&L,&R,&n);
    47     L+=maxn;  R+=maxn;
    48     for (i=1;i<=n;i++)
    49       scanf("%d%d",&bl[i],&br[i]),
    50       bl[i]+=maxn,br[i]+=maxn;
    51     for (p=n;p>=1;p--)
    52       s=bl[p],t=br[p],
    53       modify(L,R,1);
    54     for (i=1;i<=n;i++)
    55       if (cansee[i])
    56         ans++;
    57     printf("%d
    ",ans);
    58     return 0;
    59 }
  • 相关阅读:
    Docker制作tomcat镜像,发布镜像
    DockerFile
    Docker容器数据卷
    Docker镜像
    Docker部署nginx,tomcat,es,可视化
    java 使用 poi 更新 ppt 中图表的数据
    require.js与IDEA的配合
    html中require.config 缓存问题
    mongodb 更新嵌套数组的值
    java poi ppt 接口的基本操作
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/9550964.html
Copyright © 2011-2022 走看看