Ural 2064:Caterpillars(思维暴力)

http://acm.timus.ru/problem.aspx?space=1&num=2064

题意:有n只虫子在爬树,每个虫子往上爬ti距离后会往下掉落ti距离,每爬一个单位距离耗费一个单位时间,然后重新往上爬。有q个询问,询问当前的x时刻,爬的最高的虫子所在的最高位置。

思路:画个以时间为x轴,距离为y轴的图,可以清楚知道整个图是类似于一座座山峰的。我们只要处理每个时刻的最高点。

只考虑最高点所在的位置,处理出虫子能达到的最高点的时刻的最高点arrive[]。

考虑每个时刻要得到最优的两种情况:假设当前时刻为x。

1、第一种是某只虫子正在往上爬。这种情况可以考虑成时间逆流地往下掉。时间从后往前扫,对于每个时刻求出最大的arrive[i] - (i - x)。i代表之前某只虫子某个能达到的最高点的时刻。

2、第二种是某只虫子正在往下掉。这种情况将时间从前往后扫,对于每个时刻求出最大的arrive[i] - (x - i)。i的含义同上。

因为时间只有1e6,可以从后往前扫(处理出往上爬的情况)再从前往后(处理往下掉的情况)扫所有时间,处理出ans[]表。对于询问O(1)回答。

而且这题用scanf超时,用读入外挂偶尔超时,看别人代码用了“ios::sync_with_stdio(false);”取消同步,不会超时。

玄学。不懂。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000100
 4 #define M 1000004
 5 #define INF 0x3f3f3f3f
 6 int arrive[N], ans[N];
 7 
 8 int main() {
 9     ios::sync_with_stdio(false);
10     int n, t, tid, q;
11     cin >> n;
12     bool flag = 0;
13     for(int i = 1; i <= n; i++) {
14         cin >> t; if(t >= M) flag = 1;
15         for(tid = t; tid <= M; tid += 2 * t)
16             if(arrive[tid] < t) arrive[tid] = t; // arrive[tid]记录tid时刻能达到的最大高度
17         if(arrive[M] < t - (tid - M)) arrive[M] = t - tid + M; // 终点向下掉
18     }
19     for(t = 1, tid = -INF; t <= M; t++) {
20     // 时间正着往下掉: (i < t)ans[t] = max(ans[t], arrive[i] + i - t);
21         if(tid < arrive[t] + t) tid = arrive[t] + t; // 记录目前最大的arrive[i]+i
22         if(ans[t] < tid - t) ans[t] = tid - t;
23     }
24     for(t = M, tid = -INF; t >= 1; t--) {
25     // 时间逆着往下掉(向上爬): (t < i)ans[t] = max(ans[t], arrive[i] - i + t);
26         if(tid < arrive[t] - t) tid = arrive[t] - t; // 记录之前最大的arrive[i]-i
27         if(ans[t] < tid + t) ans[t] = tid + t;
28     }
29     cin >> q;
30     while(q--) {
31         cin >> t;
32         if(flag) cout << t << '
';
33         else cout << ans[t] << '
';
34     }
35     return 0;
36 }
原文地址:https://www.cnblogs.com/fightfordream/p/6409588.html