[USACO12MAR]花盆Flowerpot 解题报告
作者:互联网
题意:
给出N滴水的坐标,y表示水滴的高度,x表示它下落到x轴的位置。
每滴水以每秒1个单位长度的速度下落。你需要把花盆放在x轴上的某个位置,使得从被花盆接着的第1滴水开始,到被花盆接着的最后1滴水结束,之间的时间差至少为D。
我们认为,只要水滴落到x轴上,与花盆的边沿对齐,就认为被接住。给出N滴水的坐标和D的大小,请算出最小的花盆的宽度W。
数据范围:
40%的数据:1 ≤ N ≤ 1000,1 ≤ D ≤ 2000;
100%的数据:1 ≤ N ≤ 100000,1 ≤ D ≤ 1000000,0≤x,y≤10^6。
--------------------------------------------------我是分割线----------------------------------------------------
题解:对于40%的数据,二分花盆的宽度,朴素O(N^2)检验宽度len能否满足条件,总时间复杂度O(N^2logN),期望得分40,实际得分50。
#include<bits/stdc++.h> #define ll long long #define mp make_pair #define rep(i, a, b) for(int i = (a); i <= (b); i++) #define per(i, a, b) for(int i = (a); i >= (b); i--) using namespace std; typedef pair<int, int> pii; typedef double db; const int N = 1e6 + 50; struct node{ int x, y; } a[N]; int n, d, l = 1, r, ans = -1; inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();} while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();} return x*f; } bool mycmp(node a, node b){ return a.x < b.x; } void init(){ n = read(); d = read(); rep(i, 1, n) a[i].x = read(), a[i].y = read(), r = max(r, a[i].x); sort(a+1, a+n+1, mycmp); } bool check(int len){ int dist = 0; rep(i, 1, n){ int t = a[i].y, maxx = 0; maxx = max(maxx, a[i].y); rep(j, i+1, n){ if(i == j) continue; if(a[j].x >= a[i].x && a[j].x <= a[i].x + len) { maxx = max(maxx, a[j].y); t = min(t, a[i].y); } } dist = max(dist, abs(maxx - t)); if(dist >= d) return true; } return false; } void work(){ while(l < r){ int mid = (l+r) >> 1; if(check(mid)) r = mid, ans = mid; else l = mid + 1; } printf("%d\n", ans); } int main(){ init(); work(); return 0; }View Code
考虑对朴素算法进行优化,我们发现,检验的过程max-min的值我们可以预处理维护的,于是把整条x轴看成一个区间,每个水滴的y值看成是区间下标的权值,于是我们就不难想到ST表,运用ST表预处理区间的最大值和最小值,于是可以O(N)检验。总时间复杂度O(NlogN)。
#include<bits/stdc++.h> #define ll long long #define mp make_pair #define rep(i, a, b) for(int i = (a); i <= (b); i++) #define per(i, a, b) for(int i = (a); i >= (b); i--) using namespace std; typedef pair<int, int> pii; typedef double db; const int N = 1e5 + 50; struct node{ int x, y; } a[N]; int n, d, l = 1, r, ans = -1, maxn; int Max[N*10][21], Min[N*10][21]; inline int read(){ int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();} while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();} return x*f; } int ask_max(int l, int r){ int k = log2(r-l+1); return max(Max[l][k], Max[r - (1<<k) + 1][k]); } int ask_min(int l, int r){ int k = log2(r-l+1); return min(Min[l][k], Min[r - (1<<k) + 1][k]); } void init(){ memset(Min, 0x3f, sizeof(Min)); n = read(); d = read(); rep(i, 1, n){ a[i].x = read(), a[i].y = read(), maxn = max(maxn, a[i].x); Max[a[i].x][0] = max(Max[a[i].x][0], a[i].y); Min[a[i].x][0] = min(Min[a[i].x][0], a[i].y); } int t = log2(maxn); rep(j, 1, t) rep(i, 1, maxn - (1<<j) + 1) { Max[i][j] = max(Max[i][j-1], Max[i + (1<<(j-1))][j-1]); Min[i][j] = min(Min[i][j-1], Min[i + (1<<(j-1))][j-1]); } } bool check(int len){ rep(i, 1, maxn-len){ if(ask_max(i, i+len) - ask_min(i, i+len) >= d) return true; } return false; } void work(){ r = maxn; while(l <= r){ int mid = (l+r) >> 1; if(check(mid)) r = mid-1, ans = mid; else l = mid + 1; } printf("%d\n", ans); } int main(){ init(); work(); return 0; }View Code
标签:ch,return,int,Flowerpot,mid,while,解题,USACO12MAR,define 来源: https://www.cnblogs.com/smilke/p/11572809.html