2021牛客多校2 - WeChat Walk(分块)
題目鏈接:點擊查看
題目大意:給出 nnn 個人,再給出 mmm 對好友關系,每個人都有一個朋友圈用來顯示微信步數。現在有 qqq 次操作,每次操作會讓某個人的微信步數增加,問最后對于每個人來說,在自己朋友圈內獲得冠軍的時間
題目分析:暴力去想,因為每次都是單點更新,所以只會影響當前點和周圍相鄰點的朋友圈,但是這樣會被菊花圖卡成 O(n2)O(n^2)O(n2)
不難往分塊上去想,所以直接掛官方題解:
按照題解這樣實現細節很多,感覺如果沒有參考別人代碼的話很難寫出來。但是同時題解將本題需要思考的一些突破點都說出來了,我們嘗試換種方法繼續思考。
首先比較關鍵的幾個點是:
到此為止簡單說一下另一種解法,在原圖的基礎上,增加一個新圖:big[x]big[x]big[x] 代表點 xxx 所能到達的所有“大點”,新圖一定滿足,每個點的度數都不超過 n\sqrt{n}n?
將所有的詢問先線性維護 val[x]val[x]val[x] 代表每個點在某次詢問后的步數,因為在經過某次詢問后,修改點 xxx 后,會出現兩種情況:
所以將所有詢問按照每次更新后的 val[x]val[x]val[x] 排個序,然后從后向前處理。因為如果正著處理的話,本質上就和官方題解一樣了,倒著的話可以實現起來少處理一點細節。
我們維護三個變量:
每次遍歷到一個詢問時,自然需要更新一下兩個 last,同時需要對相鄰的“大點”更新一下其 big_mmin 變量。同時后續需要對該詢問統計答案,即“冠軍時長”,這里需要分兩種情況:
代碼:
正著遍歷(官方題解):
倒著遍歷(民間題解):
// Problem: WeChat Walk // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/11253/L // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) (x&-x) using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; vector<int>node[N],big[N]; vector<pair<int,int>>t[N]; int sq,val[N],ans[N],first_last[N],second_last[N],big_mmin[N]; int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n,m,q;read(n),read(m),read(q);sq=sqrt(n);while(m--) {int u,v;read(u),read(v);node[u].push_back(v);node[v].push_back(u);}for(int u=1;u<=n;u++) {if((int)node[u].size()>=sq) {for(auto v:node[u]) {big[v].push_back(u);}}}for(int i=1;i<=q;i++) {int u,w;read(u),read(w);val[u]+=w;t[val[u]].push_back({u,i});}for(int i=1;i<=n;i++) {second_last[i]=first_last[i]=big_mmin[i]=q;}for(int i=10000;i>=1;i--) {for(auto it:t[i]) {//遍歷每個新增加步數的位置int u=it.first,tim=it.second;for(auto v:big[u]) {//用小點更新大點的朋友圈big_mmin[v]=min(big_mmin[v],tim);}second_last[u]=first_last[u];first_last[u]=tim;}for(auto it:t[i]) {int u=it.first,tim=it.second;if((int)node[u].size()<sq) {//小點直接暴力找貢獻int mmin=second_last[u];for(auto v:node[u]) {mmin=min(mmin,first_last[v]);}ans[u]+=max(0,mmin-tim);} else {//大點直接用big_mmin計算貢獻ans[u]+=max(0,min(second_last[u],big_mmin[u])-tim);}}}for(int i=1;i<=n;i++) {printf("%d\n",ans[i]);}return 0; }總結
以上是生活随笔為你收集整理的2021牛客多校2 - WeChat Walk(分块)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021牛客多校2 - Girlfrie
- 下一篇: tourist取模模板