牛客网CSP-S提高组赛前集训营1题解(仓鼠的石子游戏 [博弈论] + 乃爱与城市的拥挤程度 [树上DP] + 小w的魔术扑克[dfs + 离线])
文章目錄
- T1:倉鼠的石子游戲
- 題目
- 題解
- 代碼實(shí)現(xiàn)
- T2:乃愛與城市擁擠程度
- 題目
- 題解
- 代碼實(shí)現(xiàn)
- T3:小w的魔術(shù)撲克
- 題目
- 題解
- 代碼實(shí)現(xiàn)
T1:倉鼠的石子游戲
題目
倉鼠和兔子被禁止玩電腦,無聊的他們跑到一塊空地上,空地上有許多小石子。兔子撿了很多石子,然后將石子擺成n個圈,每個圈由a[i]個石子組成。然后兔子有兩根彩色筆,一支紅色一支藍(lán)色。兔子和倉鼠輪流選擇一個沒有上色的石子涂上顏色,兔子每次可以選擇一個還未染色的石子將其染成紅色,而倉鼠每次可以選擇一個還未染色的石子將其染成藍(lán)色,并且倉鼠和兔子約定,輪流染色的過程中不能出現(xiàn)相鄰石子同色,誰不能操作他就輸了。假設(shè)他們兩個都使用了最優(yōu)策略來玩這個游戲,并且兔子先手,最終誰會贏得游戲?
輸入描述:
第一行輸入一個正整數(shù)T,表示有T組測試案例。
每組測試案例的第一行輸入一個n,表示有n圈石子。 第二行輸入n個正整數(shù)a[i],表示每個圈的石子數(shù)量。
輸出描述:
對于每組測試案例,如果兔子贏了,輸出”rabbit“(不含引號)如果倉鼠贏了,輸出"hamster"(不含引號)。
示例1
輸入
4
1
3
1
1
2
1 3
3
999 1000 1000000000
輸出
hamster
rabbit
rabbit
hamster
說明
對于第一組案例:只有1圈石子,并且石圈的大小為3
兔子先手,隨便找了一個石子染成紅色,接下來倉鼠后手找一個未染色的石子染成藍(lán)色,此時結(jié)果如下圖所示
如果兔子將最后一個石子染成紅色,這將導(dǎo)致相鄰石子同色,根據(jù)規(guī)則,他輸?shù)袅吮荣?#xff0c;所以倉鼠獲得了最終的勝利。
對于第二組案例:只有1圈石子,并且石圈的大小為1。
兔子先手,將唯一的一個石子染成了紅色,接下來由于沒有未著色的石子,所以倉鼠由于無法操作而輸?shù)袅吮荣?#xff0c;兔子取得了最終的勝利。
對于第三組案例:有兩個石圈,大小分別為1,3,兔子首先將大小為1的石圈中唯一一個石子染成了紅色,接下來倉鼠由于類似第一組案例中的原因輸?shù)舯荣?#xff0c;兔子取得了最終的勝利。
備注:
本題共有10組測試點(diǎn)數(shù)據(jù)。
對于前30%的數(shù)據(jù),滿足n=1,1?a[i]?7,1?T?10
對于前60%的數(shù)據(jù),滿足1?n?103,1?a[i]?7,1?T?102
對于前00%的數(shù)據(jù),滿足1?n?103,1?a[i]?109,1?T?102
對于測試點(diǎn)6,在滿足前60%的數(shù)據(jù)條件下,額外滿足a[i]=1。
題解
其實(shí)這就是一道博弈論,我們畫一畫奇環(huán),偶環(huán),推一推就找到了
ⅰ:奇環(huán)
再加上一點(diǎn)點(diǎn)理論理想推導(dǎo):
因?yàn)檫@是一個環(huán),先手選了點(diǎn)過后,后手就跟著它后面瞬移一個選點(diǎn),到最后肯定都會剩下一個點(diǎn)
而這個點(diǎn)左右一定不是相同顏色(n-1為偶數(shù),如果相同,一定會有兩個顏色點(diǎn)在某處相同),
所以這個點(diǎn)就死了,先后手都無法填充
ⅱ:偶環(huán)
按照我們之前填充的方法,不難發(fā)現(xiàn)最后這個偶環(huán)肯定是可以被填充完的,先后手都不會輸?shù)?/p>
綜上不管遇到奇環(huán)或者偶環(huán),先后手都不會死亡,并且處理的當(dāng)前環(huán)以后是無法繼續(xù)填充任何一種顏色的
所以不管哪只動物變成填充環(huán)的第一個顏色,都是一樣的效果
那最后不永遠(yuǎn)都是后手沒有地方可以選擇過后輸?shù)舯荣悊?#xff1f;
難道一直都是先手贏嗎?樣例告訴我們顯然不是。。。
觀察樣例我們發(fā)現(xiàn),真正改變輸贏的就是自環(huán)1
因?yàn)閱为?dú)成環(huán)的點(diǎn)讓無路可走的后手有了一個地方,這樣就把先手逼到了死角
但是如果又出現(xiàn)了一個單獨(dú)成環(huán)的點(diǎn),先手又重新掌握了勝局
總結(jié)一下,這道題就是判一個單獨(dú)成環(huán)的點(diǎn)的個數(shù)的奇偶性,水吧~~~~
代碼實(shí)現(xiàn)
#include <cstdio> #define MAXN 1005 int T, n, tot; int a[MAXN]; int main() {scanf ( "%d", &T );while ( T -- ) {scanf ( "%d", &n );tot = 0;for ( int i = 1;i <= n;i ++ ) {scanf ( "%d", &a[i] );if ( a[i] == 1 )tot ++;}if ( tot % 2 )printf ( "rabbit\n" );elseprintf ( "hamster\n");}return 0; }接下來就是這篇博客的重點(diǎn)所在了,寫這篇博客的意義就在于這一道題
T2:乃愛與城市擁擠程度
題目
乃愛天下第一可愛!
乃愛居住的國家有n座城市,這些城市與城市之間有n-1條公路相連接,并且保證這些城市兩兩之間直接或者間接相連。
我們定義兩座城市之間的距離為這兩座城市之間唯一簡單路徑上公路的總條數(shù)。
當(dāng)乃愛位于第x座城市時,距離城市x距離不大于k的城市中的人都會認(rèn)為乃愛天下第一可愛!
認(rèn)為乃愛天下第一可愛的人們決定到乃愛所在的城市去拜訪可愛的乃愛。
我們定義這些城市的擁擠程度為:
距離城市x距離不大于k的城市中的人到達(dá)城市x時經(jīng)過該城市的次數(shù)。例如:
假設(shè)k=2,乃愛所在的城市是1號城市,樹結(jié)構(gòu)如上圖所示時,受到影響的城市為1,2,3,4,5,因?yàn)槲鍌€城市距離1號城市的距離分別為:0,1,2,2,2,所以這五個城市都會認(rèn)為乃愛天下第一。
1號城市到1號城市經(jīng)過了1號城市。
2號城市到1號城市經(jīng)過了1號、2號城市。
3號城市到1號城市經(jīng)過了1號、2號、3號城市。
4號城市到1號城市經(jīng)過了1號、2號、4號城市。
5號城市到1號城市經(jīng)過了1號、2號、5號城市。
所以1號城市的擁擠程度是5,2號城市的擁擠程度是4,3號、4號、5號城市的擁擠程度都是1。
現(xiàn)在小w想要問你當(dāng)乃愛依次位于第1、2、3、4、5…n座城市時,有多少座城市中的人會認(rèn)為乃愛天下第一,以及受到影響城市的擁擠程度的乘積,由于這個數(shù)字會很大,所以要求你輸出認(rèn)為乃愛天下第一的城市擁擠程度乘積mod 10^9+7后的結(jié)果。
輸入描述:
第一行是兩個正整數(shù)n,k表示城市數(shù)目,
以及距離乃愛所在城市距離不大于k的城市中的人認(rèn)為乃愛天下第一!
接下來n-1行,每行兩個正整數(shù)u,v,表示樹上一條連接兩個節(jié)點(diǎn)的邊。
輸出描述:
輸出兩行
第一行n個整數(shù),表示當(dāng)乃愛依次位于第1、2、3、4、5…n座城市時,
有多少座城市中的人會認(rèn)為乃愛天下第一
第二行n個整數(shù),表示當(dāng)乃愛依次位于第1、2、3、4、5…n座城市時,
受影響的城市擁擠程度乘積mod 10^9+7后的結(jié)果。
示例1
輸入
7 2
1 2
2 3
2 4
2 5
5 6
5 7
輸出
5 7 5 5 7 4 4
20 21 20 20 28 12 12
備注:
本題共有10組測試點(diǎn)數(shù)據(jù)。
對于前10%的測試點(diǎn)滿足1?n?10,1?k?10,樹結(jié)構(gòu)隨機(jī)生成
對于前30%的測試點(diǎn)滿足1?n?103,1?k?10,樹結(jié)構(gòu)隨機(jī)生成
對于前70%的測試點(diǎn)滿足1?n?105,1?k?10,樹結(jié)構(gòu)隨機(jī)生成
對于前1100%的測試點(diǎn)滿足1?n?105,1?k?10,樹結(jié)構(gòu)為手動構(gòu)造
對于測試點(diǎn)4,在滿足其前70%的測試點(diǎn)條件下,額外滿足k=1
對于測試點(diǎn)5,在滿足其前70%的測試點(diǎn)條件下,額外滿足k=2
對于測試點(diǎn)10,在滿足其前100%的測試點(diǎn)條件下,額外滿足樹結(jié)構(gòu)退化成一條鏈
題解
我們設(shè)son[i][j]son[i][j]son[i][j]:表示以i作為根節(jié)點(diǎn)時,與i的距離小于等于j的所有的節(jié)點(diǎn)數(shù)
同時設(shè)dp[i][j]dp[i][j]dp[i][j]:表示以i作為根節(jié)點(diǎn)時,與i的距離小于等于j的所有節(jié)點(diǎn)數(shù)的擁擠程度的乘積
那么答案自然而然就是son[i][k],dp[i][k]son[i][k],dp[i][k]son[i][k],dp[i][k]
前提:要明白單個點(diǎn)x對于答案的貢獻(xiàn)就是乘上它的擁擠程度也就是它的兒子節(jié)點(diǎn)數(shù)son
首先我們就以1為根節(jié)點(diǎn),先跑一遍樹上DP,得到最初的所有son[i][j],dp[i][j]son[i][j],dp[i][j]son[i][j],dp[i][j]
接著就再跑一次DP,得到以x為根節(jié)點(diǎn)的每一種情況的對應(yīng)答案
那么我們怎么進(jìn)行轉(zhuǎn)移呢???
上圖講解:↓圖很重要哦!!!建議大家多畫一畫跟著下面一步步推,確實(shí)有點(diǎn)難以理解
假設(shè)現(xiàn)在我們正在u節(jié)點(diǎn),與u的距離為j,要更新v節(jié)點(diǎn),與v的距離為j+1的答案時
(1):
可以知道要 求與v的距離為j時,v所選的所有子樹會全部被包含到 求與v的父親u的距離為j+1時的答案中
并且這些子樹的貢獻(xiàn)是不變的,
(2):
當(dāng)我們選v為根節(jié)點(diǎn)的時候,建立在(1)的基礎(chǔ)上,就會發(fā)現(xiàn)我們統(tǒng)計了一些錯誤的節(jié)點(diǎn),
①:u的答案貢獻(xiàn)明顯錯誤,因?yàn)榘趘的子樹中的節(jié)點(diǎn)被u錯誤計算了,要除掉
看圖↑:
u對v的貢獻(xiàn)就要排除掉被v包含的v,v1,v2三個點(diǎn)的貢獻(xiàn),
所以u對v的貢獻(xiàn)就是紅圈減去紅圈與黃圈的并集
如果v1,v2與u的距離為j的話,v1,v2與v的距離就只有j-1
所以此時的狀態(tài)轉(zhuǎn)移方程式就是:
dp[v][j+1]=dp[v][j+1]?inv(son[u][j])dp[v][j+1]=dp[v][j+1]*inv(son[u][j])dp[v][j+1]=dp[v][j+1]?inv(son[u][j])%mod?(son[u][j]?(j?son[v][j?1]:0))mod*(son[u][j] - ( j ? son[v][j - 1] : 0 ))mod?(son[u][j]?(j?son[v][j?1]:0))
inv(x)表示x在模mod意義下的逆元
乘以inv(son[u][j])inv(son[u][j])inv(son[u][j])就意味者先把錯誤的u的貢獻(xiàn)除掉
乘以son[u][j]?(j?son[v][j?1]:0)son[u][j] - ( j ? son[v][j - 1] : 0 )son[u][j]?(j?son[v][j?1]:0)意味著乘上真正的u的貢獻(xiàn)
注意:如果j為0意味著只包含u自己,他就不會發(fā)生對v的轉(zhuǎn)移
②v自己的貢獻(xiàn)也明顯錯誤,因?yàn)関可以通過u再擴(kuò)散j層,它本身的擁擠程度就該加上u擴(kuò)散的第j層的個數(shù)
當(dāng)然這中間還是會包含到①所提到的在v的子樹范圍內(nèi)的某些節(jié)點(diǎn),
看圖↑:
如果v1,v2與b1,b2,b3,b4是u為根時同一層的節(jié)點(diǎn),b1,b2,b3,b4代表著u的其他子樹里面的節(jié)點(diǎn)
b1,b2…與u的距離為j-1的話,b1,b2…與v的距離就是j,但是v1,v2與v的距離是j-2
v的擁擠程度就要多上b1,b2,b3,b4這一層的點(diǎn),但是這一層里面包含了v的子節(jié)點(diǎn)v1,v2,必須減掉
所以此時的狀態(tài)轉(zhuǎn)移方程式是:
son[v][j+1]=son[v][j+1]+son[u][j]?(j?son[v][j?1]:0)son[v][j+1]=son[v][j+1]+son[u][j] - ( j ? son[v][j - 1] : 0 )son[v][j+1]=son[v][j+1]+son[u][j]?(j?son[v][j?1]:0)
dp[v][j+1]=dp[v][j+1]?inv(son[v][j+1])dp[v][j+1]=dp[v][j+1]*inv(son[v][j + 1])dp[v][j+1]=dp[v][j+1]?inv(son[v][j+1])%mod?son[v][j+1]mod*son[v][j+1]mod?son[v][j+1]%modmodmod
乘以inv(son[v][j+1])inv(son[v][j + 1])inv(son[v][j+1])意味著先把錯誤的v的貢獻(xiàn)除掉
son[v][j+1]son[v][j+1]son[v][j+1]的轉(zhuǎn)移就是v的真正包含的節(jié)點(diǎn)數(shù)
最后再乘以son[v][j+1]son[v][j+1]son[v][j+1]就是算上了正確的v的貢獻(xiàn)
③:算了u,v各自的真正貢獻(xiàn),還要乘上原本的dp[u][j]dp[u][j]dp[u][j]這時候這里面就是正確的貢獻(xiàn)乘積
但是我們發(fā)現(xiàn),答案會錯誤,因?yàn)槲覀儼?span id="ozvdkddzhkzd" class="katex--inline">dp[v][j?1]dp[v][j-1]dp[v][j?1]的總體貢獻(xiàn)多算了兩次
dp[v][j?1]dp[v][j-1]dp[v][j?1]的貢獻(xiàn)既在dp[v][j+1]dp[v][j+1]dp[v][j+1]原本的答案中,又被包含在了dp[u][j]dp[u][j]dp[u][j]中,
所以我們得把它剔除掉一次,也就是乘上它的逆元
最后真正的DP轉(zhuǎn)移方程式就是綜合以上所有情況
代碼實(shí)現(xiàn)
如果實(shí)在看不懂dfs2的,可以評論告訴我,我再解釋得更詳細(xì)一點(diǎn)
#include <cstdio> #include <vector> using namespace std; #define mod 1000000007 #define LL long long #define MAXN 100005 vector < int > G[MAXN]; int n, k; LL dp[MAXN][15], son[MAXN][15];LL qkpow ( LL x, LL y ) {LL ans = 1;while ( y ) {if ( y & 1 )ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }void dfs1 ( int u, int fa ) {for ( int i = 0;i <= k;i ++ )dp[u][i] = son[u][i] = 1;for ( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if ( v == fa ) continue;dfs1 ( v, u );for ( int j = 1;j <= k;j ++ ) {son[u][j] += son[v][j - 1];dp[u][j] = dp[u][j] * dp[v][j - 1] % mod;}}for ( int i = 1;i <= k;i ++ )dp[u][i] = dp[u][i] * son[u][i] % mod; }void dfs2 ( int u, int fa ) {for ( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i];if ( v == fa )continue;for ( int j = k - 1;j >= 0;j -- ) {LL inv_u = qkpow ( son[u][j], mod - 2 );LL inv_v = qkpow ( son[v][j + 1], mod - 2 );LL inv_same = j ? qkpow ( dp[v][j - 1], mod - 2 ) : 1;dp[v][j + 1] = dp[v][j + 1] * inv_v % mod;LL tson = son[u][j] - ( j ? son[v][j - 1] : 0 );son[v][j + 1] += tson;dp[v][j + 1] = dp[v][j + 1] * son[v][j + 1] % mod * dp[u][j] % mod * inv_u % mod * tson % mod * inv_same % mod;}dfs2 ( v, u );} }int main() {scanf ( "%d %d", &n, &k );for ( int i = 1;i < n;i ++ ) {int u, v;scanf ( "%d %d", &u, &v );G[u].push_back( v );G[v].push_back( u );}dfs1 ( 1, 0 );dfs2 ( 1, 0 );for ( int i = 1;i < n;i ++ )printf ( "%lld ", son[i][k] );printf ( "%lld\n", son[n][k] );for ( int i = 1;i <= n;i ++ ) printf ( "%lld ", dp[i][k] );return 0; }T3:小w的魔術(shù)撲克
題目
小w喜歡打牌,某天小w與dogenya在一起玩撲克牌,這種撲克牌的面值都在1到n,原本撲克牌只有一面,而小w手中的撲克牌是雙面的魔術(shù)撲克(正反兩面均有數(shù)字,可以隨時進(jìn)行切換),小w這個人就準(zhǔn)備用它來出老千作弊。小w想要打出一些順子,我們定義打出一個l到r的順子需要面值為從l到r的卡牌各一張。小w想問問你,他能否利用手中的魔術(shù)卡牌打出這些順子呢?
輸入描述:
首先輸入一行2個正整數(shù)n,k,表示牌面為1~n,小w手中有k張魔術(shù)撲克牌。
然后輸入k行,每行兩個數(shù)字,表示卡牌的正面和反面的面值。
接下來輸入一行一個正整數(shù)q,表示q組查詢,然后每組占一行查詢輸入兩個整數(shù)l,r。表示查詢小w能否打出這么一個l到r的順子。
輸出描述:
對于輸出"Yes"表示可以,"No"表示不可以。(不含引號)
每個查詢都是獨(dú)立的,查詢之間互不影響。
示例1
輸入
5 3
1 2
2 3
4 4
3
1 2
2 4
1 4
輸出
Yes
Yes
No
說明
對于順子1~2,可以選擇第一張卡牌作為’1’使用,選擇第二張卡牌作為’2’使用
對于順子2~4,可以選擇第一張卡牌作為’2’使用,選擇第二張卡牌作為’3’使用,選擇第三張卡牌作為’4’使用
對于順子1~4,由于牌的數(shù)目都不夠,顯然無法打出
示例2
輸入
4 3
1 1
2 2
4 4
3
1 2
1 4
4 4
輸出
Yes
No
Yes
說明
該樣例具有測試點(diǎn)4的特殊性質(zhì)。
備注:
本題共有10組測試點(diǎn)數(shù)據(jù)。
對于前10%的測試點(diǎn),保證1?n?10,1?k?10,1?q?10,1?l?r?n
對于前20%的測試點(diǎn),保證1?n?11,1?k?10,1?q?100,1?l?r?n
對于前30%30%的測試點(diǎn),保證1?n?50,1?k?50,1?q?500,1?l?r?n
對于前100%的測試點(diǎn),保證1?n?105, 1?k?105,1?q?105,1?l?r?n
對于測試點(diǎn)4,在滿足前100%的測試點(diǎn)條件下,額外保證所有卡牌正面上的數(shù)字等于其反面上的數(shù)字,但不同撲克牌上的數(shù)字不保證相同。
題解
真的要吐槽一波用心做題目,用腳造數(shù)據(jù)
1.你忽視牌的背面,不管怎樣詢問都只用牌的正面,據(jù)說有50pots
2.你把牌的兩面一次性都用上,據(jù)說有70pots
我有必要花大量時間去搞一個正解???
接下來進(jìn)入100pots部分:
一張牌只能變成正面或者反面,我們就把這張牌建一條邊,把兩個值連接起來
這樣我們就把1~n的牌值處理成了三個部分:
①沒有一張牌能變成i,自環(huán);②部分牌值形成了一棵樹;③部分牌值形成了一個環(huán)(連通塊)
并且不同的連通塊,樹是彼此獨(dú)立的,不然它們應(yīng)該能形成一個更大的樹或者連通塊
可以知道,如果對于一個連通塊,邊數(shù)大于等于點(diǎn)數(shù),
那么這個連通塊里面的每一個值都可以一次性全部出現(xiàn)
對于一棵樹,邊數(shù)小于點(diǎn)數(shù),
那么這棵樹里面最多只能同時出現(xiàn)點(diǎn)數(shù)-1的值,不可能同時出現(xiàn)
因?yàn)槲覀兘ǖ倪吘拖喈?dāng)于一張牌,邊連接的兩個節(jié)點(diǎn)就相當(dāng)于正反面的值
一條邊只能選擇所連的一個節(jié)點(diǎn)進(jìn)行呈現(xiàn),樹就意味著少了一條邊,也就少了一個點(diǎn)擁有呈現(xiàn)的機(jī)會
接下來我用類比的思想來幫助大家理解:假設(shè)我們有10項(xiàng)作業(yè)
樹:就意味著我們手上只有9個作業(yè)本,那么如果老師一次性要收全部作業(yè),咱們就GG了
但如果老師作業(yè)只收≤9項(xiàng),那我們就可以完成
連通塊:就意味著我們手上有≥10個作業(yè)本,不管老師要收多少項(xiàng)作業(yè),咱都能全部交上
所以我們就可以拋開連通塊不管,只考慮樹的情況
由于樹不能完全呈現(xiàn)它的所有值,所以當(dāng)有一個查詢包含了一棵完整的樹時,那棵樹總是無法完成任務(wù)
那么我們就考慮怎么判斷這種情況:對每一棵樹進(jìn)行限定
限定當(dāng)L小于等于Min(樹上的最小值),R必須嚴(yán)格小于Max(樹上的最大值)
因?yàn)橐坏㎜小于等于Min,R大于等于Max,意味著這棵樹被完全包含,肯定是無解的
最后當(dāng)L小于等于Min的時候,R的限制會有多個,因?yàn)闃溆锌赡苡卸嗫?#xff0c;我們就需要取并集,最小的R限制
舉個栗子:有一棵樹Min1=5,Max1=10,那么這棵樹的限制就是當(dāng)L小于等于5時,R一定不能大于等于10
又有另一棵樹Min2=3,Max2=7,那么這棵樹的限制就是當(dāng)L小于等于3時,R一定不能大于等于7
綜合這兩棵樹后:當(dāng)L小于等于3,R就不能超過6,當(dāng)3<L≤5,R就不能超過9
注意:不要以為一棵樹一定出現(xiàn)了[Min,Max]里的每一個值,不然上面的解釋你會認(rèn)為是錯的
接著有一些本博主碼的時候,稍微混了一會的地方
⑴一個值只會出現(xiàn)在一棵樹或者一個環(huán)或者單獨(dú)成環(huán),不會交錯,
因?yàn)橐坏┯羞@種情況,這個值會成為一個紐扣將兩個樹或環(huán)連接在一起
⑵對于自環(huán)的點(diǎn),我們也可以把它變成一棵樹,無非就是把r的限制賦值成自己就可以解決了
代碼實(shí)現(xiàn)
#include <cstdio> #include <vector> #include <iostream> using namespace std; #define MAXN 100005 #define INF 0x7f7f7f7f int n, k, q, Max, Min, edge, dot; vector < int > G[MAXN]; int limit[MAXN]; bool vis[MAXN];void dfs ( int u ) {if ( vis[u] )//雖然這個點(diǎn)被遍歷過了,dot沒有增加,,但是通往它的邊還是增加了return;dot ++;vis[u] = 1;Max = max ( Max, u );Min = min ( Min, u );for ( int i = 0;i < G[u].size();i ++ ) {edge ++;dfs ( G[u][i] );} }int main() {scanf ( "%d %d", &n, &k );for ( int i = 1;i <= k;i ++ ) {int Front, Back;scanf ( "%d %d", &Front, &Back );G[Front].push_back ( Back );G[Back].push_back ( Front );}for ( int i = 1;i <= n;i ++ )limit[i] = INF;for ( int i = 1;i <= n;i ++ ) {if ( ! G[i].size() )limit[i] = i;else if ( ! vis[i] ) {Max = - INF;Min = INF;edge = 0;dot = 0;dfs ( i );edge >>= 1;//每一條邊我們都遍歷了兩次if ( edge < dot )//說明這是一棵樹limit[Min] = Max;}}for ( int i = n - 1;i >= 1;i -- )limit[i] = min ( limit[i + 1], limit[i] );scanf ( "%d", &q );for ( int i = 1;i <= q;i ++ ) {int l, r;scanf ( "%d %d", &l, &r );if ( limit[l] <= r )printf ( "No\n" );elseprintf ( "Yes\n" );}return 0; }再見,我想先安撫一下幼小的自己。。。。
總結(jié)
以上是生活随笔為你收集整理的牛客网CSP-S提高组赛前集训营1题解(仓鼠的石子游戏 [博弈论] + 乃爱与城市的拥挤程度 [树上DP] + 小w的魔术扑克[dfs + 离线])的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 帝国网站管理系统(EmpireCMS)-
- 下一篇: 学习有向图和无向图的强连通分量(基本概念