1. 程式人生 > >計蒜課/ 微軟大樓設計方案/中等(xjb)

計蒜課/ 微軟大樓設計方案/中等(xjb)

得到 con 設計 bre nan lan http pen 情況

題目鏈接:https://nanti.jisuanke.com/t/15772

題意:中文題誒~

思路:對於坐標為p1(x1, y1), p2(x2, y2) 的兩個核心, 其中 x1 <= x2 用 d(p1, p2) 表示兩者間最矮的大樓,則需要時間為:

對於d(p1, p2) >= min(y1, y2)情況,cnt = abs(x2 - x1) + abs(y2 - y1)

對於d(p1, p2) < min(y1, y2)情況,cnt = y1 + y2 - 2*d(p1, p2) + abs(x2 -x1)

所以對於中等難度,可以枚舉所有核心組合的情況,對於當前情況,若 cnt <= k,則計數加一;

那麽現在問題為求 d,可以用 dis[i][j] 存儲前 i 個元素 j 出現的次數,那麽只需要枚舉 h 即可得到 d(p1, p2),而 h <= 20,顯然是可行的...

代碼:

技術分享
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <math.h>
 4 #include <algorithm>
 5 #include <string.h>
 6 using namespace std;
 7 
 8 const int MAXN = 2e5 + 10;
9 int a[MAXN], x[MAXN], y[MAXN], dis[MAXN][30]; 10 11 int main(void){ 12 int n, k, m; 13 scanf("%d%d", &n, &k); 14 for(int i = 1; i <= n; i ++){ 15 scanf("%d", &a[i]); 16 for(int j = 1; j <= 20; j ++){ 17 if(j == a[i]) dis[i][j] = dis[i - 1][j] + 1
; 18 else dis[i][j] = dis[i - 1][j]; 19 } 20 } 21 scanf("%d", &m); 22 for(int i = 0; i < m; i ++){ 23 scanf("%d%d", &x[i], &y[i]); 24 } 25 int ans = 0; 26 for(int i = 0; i < m; i++){ 27 for(int j = i + 1; j < m; j++){ 28 int cnt1 = x[i], cnt2 = x[j]; 29 if(cnt1 > cnt2){ 30 int cc = cnt1; 31 cnt1 = cnt2; 32 cnt2 = cc; 33 } 34 if(cnt1 == cnt2){ 35 if(abs(y[i] - y[j]) <= k) ans++; 36 }else{ 37 int d; 38 int cc = min(y[i], y[j]); 39 for(d = 1; d <= 20; d ++){ 40 if(dis[cnt2][d] - dis[cnt1 - 1][d] > 0){ 41 break; 42 } 43 } 44 if(cc <= d){ 45 int cnt = abs(cnt2 - cnt1) + abs(y[i] - y[j]); 46 if(cnt <= k) ans ++; 47 }else{ 48 int cnt = y[i] + y[j] - 2*d + abs(cnt2 - cnt1); 49 if(cnt <= k) ans ++; 50 } 51 } 52 } 53 } 54 printf("%d\n", ans); 55 return 0; 56 }
View Code

計蒜課/ 微軟大樓設計方案/中等(xjb)