CF372D. Choosing Subtree is Fun
生活随笔
收集整理的這篇文章主要介紹了
CF372D. Choosing Subtree is Fun
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
CF372D. Choosing Subtree is Fun
Solution
想了一晚都不會,一覺醒來就悟了QwQQwQQwQ
之前一直想著如何用類似樹形DPDPDP的方法求出每一個點的貢獻再合并,然后突然發現直接枚舉區間就行了。
考慮區間確定時,其實就是求區間內節點在原樹上的斯坦納樹的點數。
我們枚舉左端點lll,顯然隨著lll的增加,rrr時非降的,因此動態維護斯坦納樹的點數即可。
因為斯坦納樹的邊數,就是每個關鍵點的深度和減去dfsdfsdfs序相鄰的關鍵點的LCALCALCA的深度和,而點數為邊數加一。每次操作會加入一個點,刪除一個點,用setsetset維護關鍵點的dfsdfsdfs序,計算貢獻即可。
Code
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-11; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int mods=1e9+7; const int MAXN=400005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } set<int> Set; vector<int> e[MAXN]; int id[MAXN],dfn[MAXN],DFN=0,dep[MAXN],mn[18][MAXN],n,Log[MAXN],sum=0,k,ans=1,num=0,eul[MAXN],ID[MAXN]; void dfs(int x,int father) {id[dfn[x]=++DFN]=x,dep[x]=dep[father]+1,ID[eul[x]=++num]=x;for (auto v:e[x])if (v!=father) {dfs(v,x);ID[++num]=x;} } void Init() {for (int i=1;i<=num;i++) mn[0][i]=dep[ID[i]];for (int i=1;i<=17;i++)for (int j=1;j<=num-(1<<i)+1;j++) mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<(i-1))]); } int getdep(int l,int r) {l=eul[id[l]],r=eul[id[r]];if (l>r) swap(l,r);int x=Log[r-l+1];return min(mn[x][l],mn[x][r-(1<<x)+1]); } void add(int x) {set<int>::iterator it=Set.lower_bound(x);int nxt,lst;if (it==Set.end()) nxt=*Set.begin(),it--,lst=*it;else if (it==Set.begin()) nxt=*it,lst=*Set.rbegin();else nxt=*it,it--,lst=*it;if (nxt==lst) sum+=getdep(lst,lst)+getdep(x,x)-getdep(x,lst)*2;else sum+=getdep(x,x)+getdep(lst,nxt)-getdep(x,nxt)-getdep(lst,x);Set.insert(x); } void del(int x) {Set.erase(Set.find(x));if (!Set.size()) return; set<int>::iterator it=Set.lower_bound(x);int nxt,lst;if (it==Set.end()) nxt=*Set.begin(),it--,lst=*it;else if (it==Set.begin()) nxt=*it,lst=*Set.rbegin();else nxt=*it,it--,lst=*it;if (nxt==lst) sum-=getdep(lst,lst)+getdep(x,x)-getdep(x,lst)*2;else sum-=getdep(x,x)+getdep(lst,nxt)-getdep(x,nxt)-getdep(lst,x); } signed main() {n=read(),k=read(),ans=1;for (int i=1,u,v;i<n;i++) u=read(),v=read(),e[u].PB(v),e[v].PB(u);Log[1]=0; for (int i=2;i<=n*2;i++) Log[i]=Log[i>>1]+1;dfs(1,0),Init(),Set.insert(dfn[1]);for (int l=1,r=1;l<n;l++){while (r<n&&sum+1<=k) r++,add(dfn[r]);if (sum+1>k) upmax(ans,r-l);else upmax(ans,r-l+1);del(dfn[l]);}printf("%d\n",ans);return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的CF372D. Choosing Subtree is Fun的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 市场调研-全球与中国软磁粉芯市场现状及未
- 下一篇: Linux-USB Gadget : P