日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

發布時間:2023/11/27 生活经验 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意

\(n\) 個人,每個人手里有一把手槍。一開始所有人都選定一個人瞄準(有可能瞄準自己)。然后他們按某個順序開槍,且任意時刻只有一個人開槍。

因此,對于不同的開槍順序,最后死的人也不同。

問最后死的人數最小值以及最大值。 \((1 \le n \le 10^6)\)

題解

不難發現是一道思博構造題。

首先考慮下最大值,我們只需要把這張圖分三種情況討論:

  1. 單個自環,貢獻為 \(1\)
  2. 一個大于 \(1\) 的環,貢獻為 \(len - 1\)
  3. 一個基環樹,貢獻為 \(size - num_{leaf}\)

對于最小值的話,我們可以不斷模擬。

具體來說就是一開始把入度為 \(0\) 的人加入,這些人是活著的,然后他們瞄準的人就是必死的。

每次考慮連續三個點就行了,他們的順序就是 活 \(\to\)\(\to\) 活 的。(其實第三個人不一定活的)

然后我們對于第三個點的入度就會 \(-1\) ,如果為 \(0\) 我們加進隊列繼續操作。(這就意味著,它在其中任何一次死了。我們都不會加進去)

然后這樣不斷操作,最后只會留下環,不難發現環上至少死 \(\displaystyle \lceil \frac{len}{2} \rceil\) 個人,這樣就可以做完了qwq

總結

構造題認真想想還是想的出來的,但是需要大膽猜想小心求證才行qwq

代碼

這道題實現起來其實有一些巧妙之處,建議讀者仔細閱讀。(參考了一下 ACist大佬的博客 )

我這個代碼加上流輸入,就可以取得 BZOJ 速度 rank1 的好成績qwq

#include <bits/stdc++.h>#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)using namespace std;inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}namespace pb_ds
{   namespace io{const int MaxBuff = 1 << 16;const int Output = 1 << 22;char B[MaxBuff], *S = B, *T = B;#define getc() ((S == T) && (T = (S = B) + fread(B, 1, MaxBuff, stdin), S == T) ? 0 : *S++)char Out[Output], *iter = Out;inline void flush(){fwrite(Out, 1, iter - Out, stdout);iter = Out;}}template<class Type> inline Type read(){using namespace io;register char ch; register Type ans = 0; register bool neg = 0;while(ch = getc(), (ch < '0' || ch > '9') && ch != '-')     ;ch == '-' ? neg = 1 : ans = ch - '0';while(ch = getc(), '0' <= ch && ch <= '9') ans = ans * 10 + ch - '0';return neg ? -ans : ans;}
}using namespace pb_ds;void File() {
#ifdef zjp_shadowfreopen ("1124.in", "r", stdin);freopen ("1124.out", "w", stdout);
#endif
}const int N = 1e6 + 1e3;int n, aim[N], deg[N], maxlive, minlive; bitset<N> dead, arrive;int main () {File();n = read<int>();For (i, 1, n) ++ deg[aim[i] = read<int>()];queue<int> Q;For (i, 1, n) if (!deg[i]) Q.push(i), ++ minlive;while (!Q.empty()) {int u = aim[Q.front()], v = aim[u]; Q.pop();++ maxlive; if (dead[u]) continue ;dead[u] = true; arrive[v] = true;if (!(-- deg[v])) Q.push(v);}For (i, 1, n) if (deg[i] && !dead[i]) {int len = 0; bool flag = false;for (register int u = i; !dead[u]; u = aim[u]) dead[u] = true, ++ len, flag |= arrive[u];if (!flag && len > 1) ++ minlive;maxlive += len / 2;}printf ("%d %d\n", n - maxlive, n - minlive);return 0;
}

轉載于:https://www.cnblogs.com/zjp-shadow/p/9477479.html

總結

以上是生活随笔為你收集整理的BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。