题目一

描述

输入n,m;n可以进行 -1,*2操作,
问至少多少次操作才能得到 m 

样例:

输入

4 5

输出

3

思路:
刚开始想复杂了!!!
简单想: 
当n小于m的时候,如果我们想要用最少的操作去接近m,
那么就是尽可能的 *2,如果超过了就减(-1操作)回去,
反过来看,如果 m 为偶数了就让 m 除以 2,
如果为 m 为奇数就,将他凑为偶数,只能是 +1 操作(因为正着是 -1 操作),

#include<cstdio>
#include<algorithm>

using namespace std;

int n, m;

int main() {
while(~scanf("%d%d", &n, &m)) {
if(n >= m) {
printf("%d\n", n-m);
}
int ans = 0;
while(m > n) {
if(m & 1) {
m++;
ans++;
}
m >>= 1;
ans++;
}
printf("%d\n", ans+n-m);
}
return 0;
}

题目二

描述

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

4

16 5

20 5

10 10

18 2

Sample Output

3

1

4

1

思路:看过有人说dp,dp应该是标程;~~不会dp~~

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

int n;
struct node {
int x; // 牌的坐标
int h; // 牌的高度
int mx; // 牌倒下后的能到达的最远位置
int index; // 牌的索引
int cnt; // 此牌能压倒的牌的数量
}a[100010];

bool cmp1(node p, node q) {
return p.x < q.x;
}

bool cmp2(node p, node q) {
return p.index < q.index;
}

int main() {
while(~scanf("%d", &n)) {
memset(a, 0, sizeof(a));
for(int i=0; i<n; i++) {
scanf("%d%d", &a[i].x, &a[i].h);
a[i].mx = a[i].x + a[i].h;
a[i].index = i;
a[i].cnt = 1;
}
// 按起始坐标位置排序
sort(a, a+n, cmp1);
for(int i=n-2; i>=0; i--) {
int j = i + 1;
int mmx = a[i].mx;
while(j < n && mmx > a[j].x) {
// 累计能压倒的牌的数量
a[i].cnt += a[j].cnt;
mmx = max(mmx, a[j].mx);
// 跳过能压倒的中间的牌
j += a[j].cnt;
}
// 更新第i-1块牌的能到达的最远位置,防止之后重复统计中间位置的牌
a[i].mx = mmx;
}
// 按起始索引排序,回到最初的位置
sort(a, a+n, cmp2);
for(int i=0; i<n; i++) {
printf("%d\n", a[i].cnt);
}
}
return 0;
}