题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4068
题意:吃鸡游戏简化为二维平面上有 n 个人 (xi,yi),空投的位置在 (x0,y0),每一秒所有人向靠近空投的位置走一步,四个方向有优先级先后(优先纵坐标),若已经在空投的位置则不变。往空投位置移动过程中,若两个或者更多人在同一点相遇(在空投相遇不算),则他们都死亡。给出空投的纵坐标,询问空投在所有横坐标中最少和最多存活的人数是多少。
题解:在最优情况下,空投的横坐标必然是某一个人的横坐标,因为这样可以保证在该横坐标的人都不会死亡;而在最坏情况下,空投的横坐标则在两个不同横坐标的人之间,若所有人横坐标都相差1,则空投横坐标也是某一个人的横坐标,所以需要考虑的横坐标最多只有 2n 个。把横坐标排序后,分别从左往右扫一遍记录每个点左边存活的人数和从右往左扫一遍每个点右边存活的人数即可,具体看代码~
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define mst(a,b) memset((a),(b),sizeof(a)) 6 #define mp(a,b) make_pair(a,b) 7 #define pi acos(-1) 8 #define pii pair<int,int> 9 #define pb push_back 10 const int INF = 0x3f3f3f3f; 11 const double eps = 1e-6; 12 const int MAXN = 1e5 + 10; 13 const int MAXM = 2e5 + 10; 14 const ll mod = 1e9 + 7; 15 16 int x[MAXN],y[MAXN]; 17 vector<int>p,vec[MAXN],ans; 18 int num[MAXM],sum[MAXM]; 19 20 int main() { 21 #ifdef local 22 freopen("data.txt", "r", stdin); 23 // freopen("data.txt", "w", stdout); 24 #endif 25 int t; 26 scanf("%d",&t); 27 while(t--) { 28 int n,y0; 29 scanf("%d%d",&n,&y0); 30 p.clear(); 31 p.push_back(0); 32 for(int i = 1; i <= n; i++) { 33 scanf("%d%d",&x[i],&y[i]); 34 vec[x[i]].clear(); 35 vec[x[i] + 1].clear(); 36 p.push_back(x[i]); 37 p.push_back(x[i] + 1); 38 } 39 sort(p.begin(),p.end()); 40 p.erase(unique(p.begin(),p.end()),p.end()); 41 for(int i = 1; i <= n; i++) vec[x[i]].push_back(y[i]); 42 int cnt = 0, pre = 0; 43 mst(sum, 0); 44 mst(num, 0); 45 for(int i = 0; i < p.size(); i++) { 46 int nx = p[i]; 47 sum[nx] = vec[nx].size(); 48 vector<int>temp; 49 for(int j = 0; j < vec[pre].size(); j++) { 50 int k = abs(1e5 + 1 - pre) + abs(y0 - vec[pre][j]); 51 num[k]++; 52 if(num[k] == 1) cnt++; 53 else temp.push_back(k); 54 } 55 for(int j = 0; j < temp.size(); j++) { 56 if(num[temp[j]]) cnt--; 57 num[temp[j]] = 0; 58 } 59 sum[nx] += cnt; 60 pre = p[i]; 61 } 62 ans.clear(); 63 mst(num, 0); 64 pre = cnt = 0; 65 for(int i = p.size() - 1; i >= 0; i--) { 66 int nx = p[i]; 67 vector<int>temp; 68 for(int j = 0; j < vec[pre].size(); j++) { 69 int k = abs(0 - pre) + abs(y0 - vec[pre][j]); 70 num[k]++; 71 if(num[k] == 1) cnt++; 72 else temp.push_back(k); 73 } 74 for(int j = 0; j < temp.size(); j++) { 75 if(num[temp[j]]) cnt--; 76 num[temp[j]] = 0; 77 } 78 sum[nx] += cnt; 79 ans.push_back(sum[nx]); 80 pre = p[i]; 81 } 82 sort(ans.begin(),ans.end()); 83 printf("%d %d ",ans[0],ans[ans.size() - 1]); 84 } 85 return 0; 86 }