[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的线段。

 #include<stdio.h>
#include<algorithm>
using namespace std;
#define mid ((l+r)>>1)
struct Cow{
int high,order_l,order_r;
}cow[];
struct Num{
int order,order2;
int x;
}num[];
bool cmp1(const Num &a,const Num &b){
return a.x<b.x;
}
bool cmp2(const Num &a,const Num &b){
return a.order<b.order;
}
bool cmp3(const Cow &a,const Cow &b){
if(a.high==b.high)return a.order_r-a.order_l<b.order_r-b.order_l;
return a.high<b.high;
}
int n;
int idx,idx2;
int ans;
bool tree[];
void push(int p){
tree[p<<]=tree[(p<<)|]=tree[p];
}
bool find(int p,int l,int r,int x,int y){
if(tree[p])push(p);
if(l>=x&&r<=y)
return tree[p];
bool is1=false,is2=false,is3=false,is4=false;
if(x<=mid)is1=find(p<<,l,mid,x,y),is3=true;
if(y>mid)is2=find((p<<)|,mid+,r,x,y),is4=true;
if(is1==is3&&is2==is4)return true;
return false;
}
void add(int p,int l,int r,int x,int y){
if(l>=x&&r<=y){
tree[p]=true;
return;
}
if(x<=mid)add(p<<,l,mid,x,y);
if(y>mid)add((p<<)|,mid+,r,x,y);
if(tree[p<<]&&tree[(p<<)|])tree[p]=true;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
int a,speed;
scanf("%d%d%d",&a,&cow[i].high,&speed);
++idx;
num[idx].x=(--a)*speed;
num[idx].order=idx+;
++idx;
num[idx].x=num[idx-].x+speed;
num[idx].order=idx+;
}
sort(num+,num+idx+,cmp1);
for(int i=;i<=idx;){
int tmp=;
++idx2;
while(num[i].x==num[i+tmp].x)
num[i+tmp].order2=idx2,++tmp;
i+=tmp;
}
sort(num+,num+idx+,cmp2);
for(int i=;i<=idx;i++){
(num[i].order%)?
cow[num[i].order/].order_r=num[i].order2:
cow[num[i].order/].order_l=num[i].order2;
}
sort(cow+,cow+n+,cmp3);
for(int i=;i<=n;i++){
if((!find(,,idx2,cow[i].order_l,cow[i].order_r-))){
ans++;
}
add(,,idx2,cow[i].order_l,cow[i].order_r-);
}
printf("%d",ans);
}

[USACO15JAN]踩踏Stampede的更多相关文章

  1. P3114 [USACO15JAN]踩踏Stampede

    题目链接 我一开始看错题了,看成每秒走\(c_i\)个单位了,于是样例答案就变成了3..害我调好久,还以为样例错了 对于每头奶牛,我们求出它经过\(y\)轴的时间段,然后离散化一下,将奶牛按照从低到高 ...

  2. words

    conscious[英][ˈkɒnʃəs][美][ˈkɑnʃəs]consensus[英][kənˈsensəs][美][kənˈsɛnsəs] scious sensuswaterflood; de ...

  3. 品牌营销:不要Beat,要逼格!

             品牌营销:不要Beat,要逼格! 奥美的创始人大卫·奥格威说,广告营销应当是"具有风度的推销产品".而当下的营销手段,"风度"早已被抛之脑后, ...

  4. 布里斯班Twilight Bay Run半程马拉松

    自从8月3日跑了半马以后,又一鼓作气报了11月份的西昌马拉松.与第一次马拉松的只求完赛目标不同,第二次当然想取得一个更好的成绩.所以8月份练的比较猛,基本上是练2.3天休息一天,周么还要拉个长于21公 ...

  5. Bzoj3041 水叮当的舞步

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 132  Solved: 75 Description 水叮当得到了一块五颜六色的格子形地毯作为生日礼物 ...

  6. DevOps is dirty work - CI drives you crazy

    一直很想谈谈Continuous Integration(CI),持续集成. 就在不久前一次朋友聚会上,一个刚刚跳槽到一家创业公司的朋友跟我抱怨说他们没有CI,没有code review,要做点事太累 ...

  7. 【SIGGRAPH】【最终幻想XV】的战斗场景实时演示的要点解说

    [SIGGRAPH][最终幻想XV]的战斗场景实时演示的要点解说 原文:西川善司 http://www.4gamer.net/games/999/G999902/20160730004/        ...

  8. 【4412嵌入式开发板学习笔记】认识uboot

    转自迅为讨论群:http://www.topeetboard.com 重要说明:这份笔记不是4412开发配套的,是我在网上看视频的时候下载上课老师的笔记后修改的.所以我试了一下笔记上的uboot命令, ...

  9. UIView.frame的骗局

    如果你刚刚开始接触IOS编程, 刚刚接触UIKit, 肯定会被 frame, bounds, center, layer.anchorPoint, layer.position 这些乱七八糟得属性折腾 ...

随机推荐

  1. 实验6 流类库与I/O

    Part2 基础练习 使用文件I/O流,以文本方式打开Part1中合并后的文件,在文件最后一行添加字符"merge successfully. " // 合并两个文件内容到一个新文 ...

  2. JS 对于回调函数的理解,和常见的使用场景应用,使用注意点

      很经常我们会遇到这样一种情况: 例如,你需要和其他人合作,别人提供数据,而你不需要关注别人获取或者构建数据的方式方法. 你只要对这个拿到的数据进行操作. 这样,就相当于我们提供一个外在的函数,别人 ...

  3. Robotium之Android控件定位实践和建议

    本人之前曾经撰文描述Appium和UIAutomator框架是如何定位Android界面上的控件的. UIAutomator定位Android控件的方法实践和建议Appium基于安卓的各种FindEl ...

  4. 利用python多线程模块实现模拟接口并发

    import requestsimport jsonimport threadingimport timeimport uuid class postrequests(): def __init__( ...

  5. HDU 4178 模拟

    Roll-call in Woop Woop High Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  6. php开启子进程处理

    $pageNum = ceil($totalNum/$pageSize); for($page=1;$page<=$pageNum;$page++){ $this->o_pcntl-> ...

  7. hdu 3721 树的直径

    思路:枚举+树的直径 #include<iostream> #include<cstring> #include<cstdio> #include<algor ...

  8. Android注入完全剖析

    0 前沿 本文主要分析了一份实现Android注入的代码的技术细节,但是并不涉及ptrace相关的知识,所以读者如果不了解ptrace的话,最好先学习下ptrace原理再来阅读本文.首先,感谢源代码的 ...

  9. 预编译scss以及scss和less px 转rem

    预编译scss步骤: 1 搜索ruby并安装,点击 2 安装sass: 3 在hubuilder工具中设置预编译: 触发命令地址为ruby安装地址 命令参数为 %FileName% %FileBase ...

  10. 查找String中出现最多字符的次数和个数

    Sting 的charAt方法返回相应位置的字符,使用该方法遍历String,将每个字符存入对象属性,遍历属性得到最多字符个数 <!DOCTYPE html> <html> & ...