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

歡迎訪問 默认站点!

默认站点

當前位置: 首頁 >

codeforces gym-101745 C-Infinite Graph Game 分块

發布時間:2023/12/3 50 豆豆
默认站点 收集整理的這篇文章主要介紹了 codeforces gym-101745 C-Infinite Graph Game 分块 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意

題目鏈接
給出一個頂點帶權無向圖。
定義訪問操作:訪問一個點,就要把與這個點相鄰的點的權值全部都加到答案里去,然后給這個頂點的權值/2。現在給出一個無窮的訪問序列中的一個循環節,求最終答案的極限是多少。
注意:本題是在模意義下。

題解

數據范圍 ≤ 100000
我們定義一個sumsum數組,其中sum[v]sum[v]表示與vv頂點相鄰的所有頂點的權值和。
這樣我們掃描一個循環節,只需要把當前頂點v的sum[v]sum[v]加入到答案里面去就好了,然后我們要給頂點vv的權值減半,并且還要更新頂點vv相鄰的所有點的sumsum。
這個思路看起來沒有問題,但是問題來了,更新頂點v相鄰的所有點的sumsum值的時候,如果每個點相鄰的點都有99999個這么多。而循環節長度又有100000個這么長,時間復雜度顯然就會爆炸了。

我們現在需要一個O(nn)O(nn)的算法。

我們把頂點進行分類,按照這個頂點的度數進行分。
degv>300degv>300的點,我們把它看作是big點,如果某個點u與big點點相臨,那么這個u點的sum[u]sum[u]中不應該包含big點的權值,這樣的話,big點就不需要更新周圍點的sum值了。

degv300degv≤300的點,我們把它看作是small點,如果某個點u與small點相鄰,那么這個u點的sum[u]sum[u]中應該包含small點的權值,并且訪問small點時候,也應該從small點出發更新相鄰點的sumsum值。

這樣的話,更新操作的時間復雜度就變成了O(k?300)O(k?300)
我們繼續來看詢問操作,每次到一個點的時候,把這個點的sum[u]sum[u]加到答案里去,并且還要把這個點相鄰的big點的權值加到答案里去(因為此時sum[u]sum[u]中并不包含big點的權值)

m是邊數,最大為100000
每個點最多有m300=300m300=300個big點。因此詢問的時間復雜度也是O(k?300)O(k?300)
這樣總的時間復雜度就是O(k?300)O(k?300)

這道題還沒有做完

我們剛剛求的只是一輪循環節的答案,我們現在需要求極限值。

而第一輪的答案與第二輪的答案沒有任何比例關系。

這迫使我們去尋找組成第一輪答案的部分與組成第二輪答案的部分之間有沒有關系。

我們設頂點vv,初始權值為val[v]val[v],在第一輪中的貢獻為x1x1,那么肯定有x1=p?val[v]x1=p?val[v],其中p代表一個比例系數。

在第一輪以后,vv的權值變成了val[v]?12cnt[v]val[v]?12cnt[v],其中cnt[v]cnt[v]表示的是這個vv點在循環節中出現的次數。

第二輪中vv對答案的貢獻是x2x2,那么x2=p?val[v]?12cnt[v]x2=p?val[v]?12cnt[v]

這樣推導下去,并對所有的xx求和得到

sumx=p?val[v]1?2?cnt[v]sumx=p?val[v]1?2?cnt[v]

關鍵點來了!!!
注意看sumxsumxx1x1的形式關系,發現就相當于用val[v]1?2?cnt[v]val[v]1?2?cnt[v]替換了val[v]val[v]
因此,我們想到了解題方案,就是一開始就對所有點的權值按照這個關系進行替換,然后跑一輪循環節,得到的答案就是要求的極限。

這道題還沒有做完
這道題不一定會有極限,如果沒有極限,要輸出-1。
怎么判定有沒有極限呢?
如果一個點被訪問了,那么周圍點的權值都會被加到答案里面去,所以周圍點的權值必須減少,如果發現一個點被訪問了,而在循環節結束后,還有一個周圍相鄰的點的權值沒有被減少,那么意味著肯定不會收斂。

終于講完了,如果覺得好就點個贊吧。

代碼

#include <iostream> #include <cstdio> #include <vector> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; #define pr(x) cout<<#x<<':'<<x<<endl const int maxn = 100007; ll n,m,k,val[maxn],s[maxn]; vector<int> G[maxn],heavy[maxn]; int deg[maxn],cnt[maxn],vis[maxn],big[maxn]; ll sum[maxn],ans[maxn]; const ll mod = 1e9+7; long long powmod(long long x, long long p){long long res = 1;while(p > 0){if(p % 2 == 1) res = res * x % mod;x = x * x % mod;p >>= 1;}return res; } ll mi[maxn],inv[maxn]; int main(){inv[0] = mi[0] = 1;for(int i = 1;i < maxn;++i)mi[i] = 2ll*mi[i-1]%mod;inv[1] = powmod(2,mod-2);for(int i = 2;i < maxn;++i)inv[i] = inv[1]*inv[i-1]%mod;scanf("%lld%lld%lld",&n,&m,&k);for(int i = 1;i <= n;++i)scanf("%lld",&val[i]);for(int i = 1;i <= k;++i)scanf("%lld",&s[i]);for(int i = 0;i < m;++i){int a,b;scanf("%d%d",&a,&b);G[a].push_back(b);G[b].push_back(a);deg[a]++;deg[b]++;}for(int i = 1;i <= n;++i)for(int j = 0;j < G[i].size();++j)if(deg[i] > 300) heavy[G[i][j]].push_back(i),big[i] = 1;for(int i = 1;i <= k;++i){cnt[s[i]]++;if(cnt[s[i]] == 1)for(int j = 0;j < G[i].size();++j)vis[G[i][j]] = 1;}for(int i = 1;i <= n;++i){if(vis[i] && !cnt[i] && val[i] > 0)return 0*puts("-1");}for(int i = 1;i <= n;++i){val[i] = val[i]*powmod((1-inv[cnt[i]]+mod)%mod,mod-2)%mod;}for(int i = 1;i <= n;++i){if(big[i]) continue;for(int j = 0;j < G[i].size();++j)sum[G[i][j]] = (sum[G[i][j]] + val[i])%mod;}ll res = 0;for(int i = 1;i <= k;++i){int u = s[i];res = (res + sum[u])%mod;for(int j = 0;j < heavy[u].size();++j){int v = heavy[u][j];res = (res + val[v])%mod;}ll old = val[u];val[u] = old*inv[1]%mod;//val[u] = val[u]*inv[1]%mod;if(!big[u]){for(int j = 0;j < G[u].size();++j){int v = G[u][j];sum[v] = (sum[v] - old + val[u] + mod)%mod;}} }cout<<res<<endl;return 0; }

總結

以上是默认站点為你收集整理的codeforces gym-101745 C-Infinite Graph Game 分块的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得默认站点網站內容還不錯,歡迎將默认站点推薦給好友。