2014百度之星初赛第二轮解题报告:Scenic Popularity
Scenic Popularity
时间限制: 1s 内存限制: 65536K
问题描述
临近节日,度度熊们最近计划到室外游玩公园,公园内部包括了很多的旅游景点区和休息区,由于旅游景点很热门,导致景点区和休息区都聚集了很多人。所以度度熊在旅游之前想通过百度地图查看一下公园内各个地方的热门程度。
假设所有景点区和休息区都是X轴直线上的一系列顶点,所对应的坐标Xi 保证唯一。每个景点区有个初始的热度值,而一个休息区(坐标为Xi)的热度值等于离它距离最近的景点区Xj的热度值(距离定义为|Xi-Xj|),如果此休息区与两个景点区的距离一样,则休息区的热度值选择两个景点区中的热度值最大值,如果两个热度值都一样,则随意选择其中一个。
度度熊在出门之前会经常去查看百度地图,每次查看前会有某些景点区的热度值已发生改变,从而也会导致周围的休息区的热度值发生改变,然后度度熊想知道当前热度值<=Rk的顶点(包括景点区和休息区)有多少个
输入
输入数据的第一行是测试Case的个数(T<=100)。
每个Case的第一行是N(0<N<=10000),表示景点区和休息区的总数。
接着会有N行数据,每一列首先是顶点的X坐标Xi (0< Xi <=1e8),第二列是一个整数Hi(0=<Hi<=100000),如果Hi 不为0,则表示当前顶点为风景区且初始的热度值为Hi,否则表示当前顶点为休息区。这N行数据会按照坐标Xi递增的方式依次给出。
接着的一行数据是操作的次数K(k<=100),最后会有K行数据,每一行的第一列要么是’U’或者’Q’,’U’表示当前操作为更改热度操作,’Q’表示当前操作为查询操作。如果是更改操作,接着会有两列数据,分别是热度值要改变的风景区的下标Lk(0<=L<N)以及改变后的热度值Vk(0< Vk<=100000);如果是查询操作,第二列是要查询的热度范围Rk(0< Rk<=100000)
输出
对于第k组测试数据,第一行输出Case #k:,接下来对每次查询操作(即Q操作)会输出一个整数,表示满足条件的顶点数有多少个
样例输入
1
4
10 0
20 3
30 0
40 2
3
Q 3
U 3 4
Q 3
样例输出
Case #1:
4
2
解题报告:
整道题主要是考虑如何降低查询和更新的复杂度,解决思路也是传统的树状数组统计方式。但是需要注意的是细节上的处理,每次景区的热度值都会导致多个休息区的热度发生变更,而需要特别处理的主要是一些特殊的休息区,这种特殊的休息区与两个景区的距离一样,因此需要引入额外的标志来记录当前休息区是与哪个景区的热度值是匹配的。
解题代码:
#include <stdio.h> #include <string.h> const int MAXN = 10000; const int MAXM = 100000; int n; int coord[MAXN]; int heat_value[MAXN]; int is_scenic[MAXN]; int lscenic_idx[MAXN]; int rscenic_idx[MAXN]; int range_count[MAXM + 1]; inline int cmp_coord(int l, int m, int r) { if (l == -1) return 1; if (r == -1) return -1; int d = (coord[m] - coord[l]) - (coord[r] - coord[m]); return d == 0 ? 0 : (d < 0 ? -1 : 1); } void update() { memset(range_count, 0, sizeof(range_count)); for (int s = 0; s < n; s++) { if (is_scenic[s] == 0) { int l = lscenic_idx[s]; int r = rscenic_idx[s]; int c = cmp_coord(l, s, r); if (c == 0) { heat_value[s] = (heat_value[l] >= heat_value[r] ? heat_value[l] : heat_value[r]); } else if (c < 0) { heat_value[s] = heat_value[l]; } else { heat_value[s] = heat_value[r]; } } range_count[heat_value[s]]++; } } void init_data() { for (int i = 0; i < n; i++) { lscenic_idx[i] = (is_scenic[i] == 1 ? i : (i == 0 ? -1 : lscenic_idx[i - 1])); } for (int i = n - 1; i >= 0; i--) { rscenic_idx[i] = (is_scenic[i] == 1 ? i : (i == n - 1 ? -1 : rscenic_idx[i + 1])); } update(); } int query(int range) { int cnt = 0; for (int i = 1; i <= range; i++) { cnt += range_count[i]; } return cnt; } int main() { int KK = 1; int T, Q; char cmd[10]; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d %d", &coord[i], &heat_value[i]); is_scenic[i] = (heat_value[i] > 0 ? 1 : 0); } init_data(); printf("Case #%d:\n", KK++); scanf("%d", &Q); while (Q--) { int s, chv, range; scanf("%s", cmd); if (cmd[0] == 'U') { scanf("%d %d", &s, &chv); heat_value[s] = chv; update(); } else { scanf("%d", &range); printf("%d\n", query(range)); } } } return 0; }