2017 計蒜之道 初賽 第六場(個人題解)

2022-02-27 11:43:30 字數 4191 閱讀 9961

a. 微軟手機的訊號顯示

模擬題,用乙個7*7個陣列,然後int除法判斷訊號有幾成就可以了

**:

#include using namespace std;

#define inf 0x3f3f3f3f

#define lc(x) (x<<1)

#define rc(x) ((x<<1)+1)

#define mid(x,y) ((x+y)>>1)

#define clr(arr,val) memset(arr,val,sizeof(arr))

#define fast_io ios::sync_with_stdio(false);cin.tie(0);

typedef pairpii;

typedef long long ll;

const double pi = acos(-1.0);

const int n = 10;

char s[n][n];

int main(void)

else if (b >= 6)

else

s[2][6] = 'e';

int cur = 2;

int ge = d / 20;

while (ge--)

if (cur == 3)

if (cur == 4)

if (cur == 5)

if (cur == 6)

++cur;

}for (i = 1; i <= 7; ++i)

puts(s[i] + 1);

return 0;

}

b. 微軟大樓設計方案(簡單)

模擬題+bfs,我是用乙個比較大的陣列當地圖,然後以80行為地面根據樓的高度一層一層地往上蓋樓房,然後$o(m^2)$列舉兩兩點之間bfs出距離判斷一下更新答案

**:

#include using namespace std;

#define inf 0x3f3f3f3f

#define lc(x) (x<<1)

#define rc(x) ((x<<1)+1)

#define mid(x,y) ((x+y)>>1)

#define clr(arr,val) memset(arr,val,sizeof(arr))

#define fast_io ios::sync_with_stdio(false);cin.tie(0);

typedef pairpii;

typedef long long ll;

const double pi = acos(-1.0);

const int n = 110;

int pos[n][n];

struct info

;info s, t;

int h[n];

int vis[n][n];

int dir[4][2] = ;

int check(info w)

int bfs(info s, info t)}}

return inf;

}int main(void)

info p[n];

scanf("%d", &m);

for (i = 0; i < m; ++i)

int cnt = 0;

for (i = 0; i < m; ++i)

}printf("%d\n", cnt);

return 0;

}

c. 微軟大樓設計方案(中等)

rmq+分類討論,這題一開始可以發現實際上還是可以$o(m^2)$暴力列舉兩個點然後算距離,但是這樣一來距離的計算基本得$o(1)$才行,然後又發現樓是一層一層地往上蓋的,任意兩棟樓之間至少底層可以通過,因此兩個點之間的距離只跟兩個點之間的最低的樓房高度有關係,那麼就用rmq或者線段樹預處理出區間最小值,然後每一次查詢兩個點之間的樓房最低高度,這裡顯然有四種情況,(左邊小於等於和大於兩種*右邊小於等於和大於兩種),實際上後面搞清楚的話有幾種情況是一樣的,然後根據情況算距離即可。

**:

#include #include using namespace std;

#define inf 0x3f3f3f3f

#define lc(x) (x<<1)

#define rc(x) ((x<<1)+1)

#define mid(x,y) ((x+y)>>1)

#define clr(arr,val) memset(arr,val,sizeof(arr))

#define fast_io ios::sync_with_stdio(false);cin.tie(0);

typedef pairpii;

typedef long long ll;

const double pi = acos(-1.0);

const int n = 200010;

const int m = 2010;

int h[n];

struct info

;info p[m];

int min[n][19];

void rmq(int l, int r)

int st(int l, int r)

int main(void)

rmq(1, n);

scanf("%d", &m);

for (i = 1; i <= m; ++i)

scanf("%d%d", &p[i].y, &p[i].x);

int ans = 0;

for (i = 1; i <= m; ++i)

}if (dx <= k)

++ans;}}

printf("%d\n", ans);

return 0;

}

d. 微軟大樓設計方案(困難)

rmq+二分+一點思維,這題比賽的時候沒寫出來,因為想的方法就不對,以為直接從第乙個點算出到其他點的距離dis[i],然後任意兩點間的最短距離就是dis[i]-dis[j],實際上有很多情況下這種做法是錯的,原因就在於不符合最短路的性質(即使有樓層是從下往上蓋的),甚至有時候實際距離還是這兩者相加……

網上的一種做法是對x排序,即按點所在辦公樓從左到右排序,然後

用最壞的情況二分出最遠一定能到達的點,那麼什麼是最壞的情況呢,假設當前有兩個點在a號樓的最頂層和b號樓的最頂層,最壞情況就是a樓與b樓都是20層,那麼a到b的距離就是$20-1+abs(a-b)+20-1=abs(a-b)+38$,如果記abs(a-b)為δ,那麼移項並合併可以得到δ<=k-38,那麼二分的時候用兩者樓號之差的絕對值判斷即可,然後由於這是最壞情況下的二分,很可能二分的範圍之後還有一些點也是符合題目條件的,因此用最好的情況進行遍歷,即假設當前這個點在第一層,那麼可以到達最遠的樓層為當前點所在樓號$x_+k$,如果某個點的x大於$x_+k$,那麼就算這兩個點都在第一層只需要左右移動這種最好情況下也是無法到達的,更不用說其他還要上下樓的情況了,如果出現這種情況就可以break了。

**:

#include using namespace std;

#define inf 0x3f3f3f3f

#define lc(x) (x<<1)

#define rc(x) ((x<<1)+1)

#define mid(x,y) ((x+y)>>1)

#define clr(arr,val) memset(arr,val,sizeof(arr))

#define fast_io ios::sync_with_stdio(false);cin.tie(0);

typedef pairpii;

typedef long long ll;

const double pi = acos(-1.0);

const int n = 200010;

struct info

};info p[n];

int h[n], low[n][19];

int n, m, k;

void rmqinit(int l, int r)

}}int st(int l, int r)

int getpos(int l, int r, info t)

else

r = mid - 1;

}return ans;

}int main(void)

}printf("%lld\n", ans);

return 0;

}

2019 計蒜之道 初賽 第六場

a.vipkid 通過大資料和標籤來智慧型地進行師生匹配。當我們把標籤抽象成括號 匹配過程簡化為括號串的匹配,希望聰明的你來解決如下問題 判斷給定的括號序列是否合法且反回文。對於這樣標籤抽象組成的括號序列,我們有如下定義 合法的的括號序列 反回文的括號序列 如果序列長度為 ll,且字元從 00 開始...

2017 計蒜之道 初賽 第五場

ucloud 機房的網路搭建 ucloud 剛剛建立乙個新機房,近日正在進行網路搭建。機房內有 n n 臺伺服器和 m m 個分線器,整個機房只有乙個網線出口。分線器的作用是將一根網線轉換成多根網線。蒜頭君也知道每個分線器輸出的最大網線根數 不一定要將分線器輸出的每根線都用上 問你至少需要使用多少個...

2017 計蒜之道 初賽 第五場

a.ucloud 機房的網路搭建 ucloud 剛剛建立乙個新機房,近日正在進行網路搭建。機房內有 nn 臺伺服器和 mm 個分線器,整個機房只有乙個網線出口。分線器的作用是將一根網線轉換成多根網線。蒜頭君也知道每個分線器輸出的最大網線根數 不一定要將分線器輸出的每根線都用上 問你至少需要使用多少個...