• [USACO15JAN]踩踏Stampede


    [USACO15JAN]踩踏Stampede

    题目描述

    DJ站在原点上向y轴正半轴看,然后有一群奶牛从他眼前飞过。这些奶牛初始都在第二象限,尾巴在(Xi,Yi),头在(Xi+1,Yi),每Ci秒向右走一个单位。 DJ能看见一匹奶牛当且仅当它身体任意某部位x坐标为0时,没有其它y坐标小于此奶牛的奶牛身体某部位x坐标为0。 问DJ能看见多少奶牛?

    输入格式:

    第一行:一个数,给出n,表示n头牛。

    第二行:三个数,给出Xi和Yi,描述第i头牛的位置,给出Ci,描述这头牛多少秒走一个单位。

    输出格式:

     一行,给出ans,即DJ能看到多少头牛。

    输入输出样例

    输入样例#1:
    3 
    -2 1 3 
    -3 2 3 
    -5 100 1 
    
    输出样例#1:
    2 
    

    样例说明

    DJ能看到第一和第二头牛,看不到第三头牛。

    思路

      首先,每一头牛的Xi,Yi,Ci都可能非常的大,所以用普通的暴力搜索是过不去的,所以就要换一个方法去想问题,题目中给出了速度,路程,那么我们可以很容易就想到时间。以样例为例:第一头牛的头到达y轴的时间记为B1=(-2+1)*(-1)*3=3,第一头牛的尾巴到达y轴的时间记为E1=B1+3=6,就像这样我们能知道在第3秒到第6秒时第一头牛是在y轴上的;同理,我们可以知道第二头牛在第6秒到第9秒时是在y轴上的,第三头牛在第4秒到第5秒时是在y轴上的。有人会问知道这些有什么用呢?由于知道时间和纵坐标的位置,我们可以轻易的推出来任意两头牛是否有重叠,方法是当且仅当第i头牛的时间段与第j头牛的时间段有重叠,并且第i头牛的纵坐标比第j头牛的纵坐标小才能当上第j头牛。

      由于我只需要看到这头牛的一部分就算看到,那么我们每一次只需要看一下当前牛的时间段是否被覆盖了,如果没有被全被覆盖则ans++,这头牛可以被看到,并且把这个时间段全部覆盖。那么现在有一个问题了,怎么能保证每一头牛能在恰当的时间进行验证呢?我们需要把牛按纵坐标进行排序,在一一进行验证,这样就可以保证纵坐标小的牛不被纵坐标大的牛遮挡住。既然思路已经出来,那么算法十分容易分析出来,区间查询+区间修改=线段树。我们再看一下每一个数是十分大的,如果直接进行线段树覆盖会MLE,那么是不是可以把时间离散化一下?我们把时间点排序,在更形成序号就可以啦,再看样例这些牛中出现了3,6,9,4,5五个时间点,排序过后是3,4,5,6,9,那么第一头牛就可以化为在第1秒到第4秒在y轴上,第二头牛就可以化为在第4秒到第5秒在y轴上,第一头牛就可以化为在第2秒到第3秒在y轴上。这样每一次操作就十分方便了。

      注意:由于时间点重合可能是像2~3,3~4和4~5这样的时间段,那么如果直接按照时间点进行查询和覆盖就可能出现问题,比如说先覆盖2~3和4~5,那么查找3~4时便会出现问题,所以每一次覆盖和查询的是线段,比如2~6是覆盖和查询2~5的线段。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 using namespace std;
     4 #define mid ((l+r)>>1)
     5 struct Cow{
     6     int high,order_l,order_r;
     7 }cow[50001];
     8 struct Num{
     9     int order,order2;
    10     int x;
    11 }num[100001];
    12 bool cmp1(const Num &a,const Num &b){
    13     return a.x<b.x;
    14 }
    15 bool cmp2(const Num &a,const Num &b){
    16     return a.order<b.order;
    17 }
    18 bool cmp3(const Cow &a,const Cow &b){
    19     if(a.high==b.high)return a.order_r-a.order_l<b.order_r-b.order_l;
    20     return a.high<b.high;
    21 }
    22 int n;
    23 int idx,idx2;
    24 int ans;
    25 bool tree[1000000];
    26 void push(int p){
    27     tree[p<<1]=tree[(p<<1)|1]=tree[p];
    28 }
    29 bool find(int p,int l,int r,int x,int y){
    30     if(tree[p])push(p);
    31     if(l>=x&&r<=y)
    32         return tree[p];
    33     bool is1=false,is2=false,is3=false,is4=false;
    34     if(x<=mid)is1=find(p<<1,l,mid,x,y),is3=true;
    35     if(y>mid)is2=find((p<<1)|1,mid+1,r,x,y),is4=true;
    36     if(is1==is3&&is2==is4)return true;
    37     return false;
    38 }
    39 void add(int p,int l,int r,int x,int y){
    40     if(l>=x&&r<=y){
    41         tree[p]=true;
    42         return;
    43     }
    44     if(x<=mid)add(p<<1,l,mid,x,y);
    45     if(y>mid)add((p<<1)|1,mid+1,r,x,y);
    46     if(tree[p<<1]&&tree[(p<<1)|1])tree[p]=true;
    47 }
    48 int main(){
    49     scanf("%d",&n);
    50     for(int i=1;i<=n;i++){
    51         int a,speed;
    52         scanf("%d%d%d",&a,&cow[i].high,&speed);
    53         ++idx;
    54         num[idx].x=(-1-a)*speed;
    55         num[idx].order=idx+1;
    56         ++idx;
    57         num[idx].x=num[idx-1].x+speed;
    58         num[idx].order=idx+1;
    59     }
    60     sort(num+1,num+idx+1,cmp1);
    61     for(int i=1;i<=idx;){
    62         int tmp=0;
    63         ++idx2;
    64         while(num[i].x==num[i+tmp].x)
    65             num[i+tmp].order2=idx2,++tmp;
    66         i+=tmp;    
    67     }
    68     sort(num+1,num+idx+1,cmp2);
    69     for(int i=1;i<=idx;i++){
    70         (num[i].order%2)?
    71         cow[num[i].order/2].order_r=num[i].order2:
    72         cow[num[i].order/2].order_l=num[i].order2;
    73     }
    74     sort(cow+1,cow+n+1,cmp3);
    75     for(int i=1;i<=n;i++){
    76         if((!find(1,1,idx2,cow[i].order_l,cow[i].order_r-1))){
    77             ans++;
    78         }
    79         add(1,1,idx2,cow[i].order_l,cow[i].order_r-1);
    80     }
    81     printf("%d",ans);
    82 }
    View Code
  • 相关阅读:
    Silverlight 程序启动
    在RHEL 下安装PostgreSQL
    在x64 Linux上安装PostGIS
    Datalist或Repeater里点击某列内容将放到文本框中以便编辑,文本框失去焦点后信息即可修改成功
    javascript“设为首页”与“加入收藏”兼容多浏览器代码
    百度地图api 3D图层添加 代码
    百度地图api 开发日志 范围加载
    CLR via C# 第一章 (1)
    首個字母排序
    内存管理
  • 原文地址:https://www.cnblogs.com/yangsongyi/p/8664649.html
Copyright © 2020-2023  润新知