省选训练赛第4场D题(多米诺骨牌)
题目来自FZU2163 多米诺骨牌
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
Vasya很喜欢排多米诺骨牌。他已经厌倦了普通的多米诺骨牌,所以他用不同高度的多米诺骨牌。他从左边到右边,把n个多米诺骨牌沿一个轴放在桌子上。每一个多米诺骨牌垂直于该轴,使该轴穿过其底部的中心。第i个多米诺骨牌具有坐标xi与高度hi。现在Vasya想要知道,对于每一个多米诺骨牌如果他推倒的话,右侧会有多少个多米诺骨牌也会倒下。
想想看,一个多米诺倒下,如果它严格的触动右侧的多米诺骨牌,被触碰的也会倒下。换句话说,如果多米诺骨牌(初始坐标x和高度h)倒下,会导致所有在[ X + 1,x + H - 1]范围内的多米诺骨牌倒下。
Input
输入有多组测试数据,处理到文件结尾。
每组测试数据第一行包含整数n(1≤N≤10^5),这是多米诺骨牌的数量。然后n行,每行包含两个整数xi与hi(-10^8≤xi≤10^8 ,2 ≤hi≤108),xi表示多米诺骨牌的坐标和hi表示多米诺骨牌的高度。没有两个多米诺骨牌在同一个坐标点上。
Output
对于每组数据输出一行,包含n个空格分隔的数Zi - 表示倒下的多米诺骨牌数量,如果Vasya推第i个多米诺骨牌(包括多米诺骨牌本身)。
Sample Input
Sample Output
第一次比赛中出现中文题目,真心觉得高兴啊,无需百度翻译了……
这题目在比赛的时候我并没有思路,最后也没有做这题,赛后才思考这到题,一开始的想法就是动态规划,觉得是在可接触范围内的
从后面开始,dp[i]=max{1+dp[x]),x为i~i+h-1中有多米骨牌的坐标。
但是这样一想,dp开的数组太大了(10^8),且这 dp效率明显不高啊!因为这个范围内着到有坐标,明显会超时。
后来换一种思维来看,我们先按照横坐标排序,并重新编号,能推倒的多米诺牌的最后一个,肯定是不能推倒的那个的前一个,所以找到不能推倒的,再回溯回去。
这样很自然,就会使用栈结构了,我们用排序后的第一张牌压入栈,我们按新编号第二张牌开始去遍历,当前牌是栈顶部元素无法接触的时候,那么栈顶部能推倒的是这张牌的新序号减上栈顶部的新序号,并且很有可能栈中其他元素能触碰到这张牌(也按照刚刚的判断方法,是否能触碰到当前牌,能则继续pop)。当能触碰到,则继续压入栈。
即是:只在可以确定到不能触碰的时候才看开始考虑之前的牌!
所以,我们要引入一张无法触碰的,x坐标在无穷远(1<<30),这样,每个牌肯定会找到无法触碰的牌(最坏情况就是找到引入的牌)
我写了两个代码,一个是以类的形式来写,另一个是直接用数组,两者来说,第一个比较好理解。
类的形式:
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
class GP{
public:
int id;
int s_id; // sort id
int x; //横坐标
int h; //高度 GP(){}; bool operator <(const GP &g)const{ return this->x<g.x;
}
void operator =(const GP &g){
this->id=g.id;
this->s_id=g.s_id;
this->x=g.x;
this->h=g.h;
} };
vector<GP> v; //骨牌
stack<GP> stk; //栈结构
int ans[100005];//结果数组
int main(){ int i; while(scanf("%d",&n)!=EOF){
v.clear();
while(!stk.empty()){stk.pop();}
v.resize(n+1);
for(i=0;i<n;i++){
v[i].id=i;
scanf("%d%d",&v[i].x,&v[i].h); }
v[n].x=200000001; //无穷远
v[n].h=0;
v[n].s_id=n;
sort(v.begin(),v.end());
for(i=0;i<n;i++){
v[i].s_id=i; }
stk.push(v[0]);
GP tmp;
for(i=1;i<=n;i++){ while(!stk.empty()&&stk.top().x+stk.top().h-1<v[i].x){ //直到无法触及的多米诺
tmp=stk.top();
stk.pop();
// cout<<tmp.x<<" "<<tmp.s_id<<" "<<v[i].s_id<<endl;
ans[tmp.id]=v[i].s_id-tmp.s_id; }
stk.push(v[i]); } for(i=0;i<n-1;i++){ printf("%d ",ans[i]);
}
printf("%d\n",ans[n-1]); }
return 0; }
数组形式:
#include<iostream>
#include<stack>
#include<algorithm>
#include<cstdio>
using namespace std;
#define N 100005
int id[N],x[N],h[N],ans[N];
bool CMP (int a,int b){ return x[a]<x[b]; }
stack<int> stk;
int main(){
int n,i; while(scanf("%d",&n)!=EOF){ while(!stk.empty()) stk.pop();
for(i=0;i<n;i++){ scanf("%d%d",x+i,h+i);
id[i]=i; }
x[n]=1<<30;
id[n]=n; sort(id,id+n,CMP); stk.push(0);
for(i=1;i<=n;i++){ while(!stk.empty()&&x[id[stk.top()]]+h[id[stk.top()]]-1<x[id[i]]){ //无法触碰的多米诺
int j=stk.top();
stk.pop();
ans[id[j]]=i-j; } stk.push(i); }
for(i=0;i<n-1;i++){
printf("%d ",ans[i]); }
printf("%d\n",ans[n-1]); } return 0;
}
省选训练赛第4场D题(多米诺骨牌)的更多相关文章
- HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...
- 训练赛第三场A题 zoj 559
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2559 解题报告:比赛的时候的想法是可以确定至少有两对相切的圆,所 ...
- 计蒜客 ACM竞赛高校联盟训练赛 第8场 煎牛排
水一水. https://nanti.jisuanke.com/t/24205 煎牛排 题目描述 又是一个难得的周六,是时候远离食堂和外卖出去大吃一顿了.圈内知名吃货AA正想着中午去吃汉堡炸鸡烤肉火锅 ...
- 2018牛客网暑假ACM多校训练赛(第二场)E tree 动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round2-E.html 题目传送门 - 2018牛客多校赛第二场 E ...
- NOI2019省选模拟赛 第五场
爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...
- NOI2019省选模拟赛 第六场
传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...
- 2019牛客训练赛第七场 C Governing sand 权值线段树+贪心
Governing sand 题意 森林里有m种树木,每种树木有一定高度,并且砍掉他要消耗一定的代价,问消耗最少多少代价可以使得森林中最高的树木大于所有树的一半 分析 复杂度分析:n 1e5种树木,并 ...
- HDU 4941 Magical Forest(map映射+二分查找)杭电多校训练赛第七场1007
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4941 解题报告:给你一个n*m的矩阵,矩阵的一些方格中有水果,每个水果有一个能量值,现在有三种操作,第 ...
- Contest1593 - 2018-2019赛季多校联合新生训练赛第三场(部分题解)
H 10255 自然数无序拆分 H 传送门 题干: 题目描述 美羊羊给喜羊羊和沸羊羊出了一道难题,说谁能先做出来,我就奖励给他我自己做的一样礼物.沸羊羊这下可乐了,于是马上答应立刻做出来,喜羊羊见状, ...
随机推荐
- 按要求编写一个Java应用程序: (1)定义一个类,描述一个矩形,包含有长、宽两种属性,和计算面积方法。 (2)编写一个类,继承自矩形类,同时该类描述长方体,具有长、宽、高属性, 和计算体积的方法。 (3)编写一个测试类,对以上两个类进行测试,创建一个长方体,定义其长、 宽、高,输出其底面积和体积。
package jvxing; public class Jvxing { //成员变量 private double width; private double chang; public doub ...
- android 五子棋开发
两天完成基本功能,再对其进行细节bug优化,本小白的思路. 思路: 1.用canvas绘制棋盘:得到手机的分辨率.棋盘大小为19*19.将手机宽屏分为21份,取中间19份为棋盘.上下空白位置为按钮功能 ...
- 【不积跬步,无以致千里】mysql 多行合并函数
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- BZOJ 1090: [SCOI2003]字符串折叠 区间DP
1090: [SCOI2003]字符串折叠 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
- MyEclipse 10官网下载地址以及破解方法
刚刚公布了MyEclipse 10,我如今用的还是6.5的版本号,6.5的版本号是我认为最好用的一个版本号. 我装上了,还没感受到有哪些好用,就是感觉体积庞大,和IBM 的WID一样,是个多面手,啥事 ...
- html5中viewport使用
html5中viewport使用 转载自:http://www.maoegg.com/the-usage-of-viewport-in-html5/ 用html5开发移动应用时往往会遇到手机的分辨率或 ...
- 检测 NSObject 对象持有的强指针
在上一篇文章中介绍了 FBRetainCycleDetector 的基本工作原理,这一篇文章中我们开始分析它是如何从每一个对象中获得它持有的强指针的. 如果没有看第一篇文章这里还是最好看一下,了解一下 ...
- C# 之 Excel 导入一列中既有汉字又有数字:数字可以正常导入,汉字导入为空
今天在做一个Excel导入功能,一切开发就绪,数据可以成功导入.导入后检查数据库发现有一列既有汉字又有数字,数字正常导入,汉字为空.但是前面同样既有汉字又有数字的列可以导入成功. 查看excel 源文 ...
- Java基础知识强化之多线程笔记04:并行和并发 区别
1. 并发 和 并行区别 (1)并发:(单核) 并发,是在同一个cpu上同时(不是真正的同时,而是看来是同时,因为cpu要在多个程序间切换)运行多个程序. 并发是指两个任务都请求运行,而处理器只能按受 ...
- 自定义请求头信息及cookie信息
请求网页的时候有时候我们需要传递一些参数信息,这个时候我们可以将参数放到请求头中,具体使用如下: 这里有小问题就是请求参数的属性名好像不支持下划线,即 HTTP_UID不可用,但是HTTP-UID就可 ...