BZOJ2809 [Apio2012]dispatching
阿新 • • 發佈:2018-08-27
left oot patch ret 時間復雜度 log 復雜度 tchar namespace
分析
假設確定了\(i\)號節點,那麽就應該是在\(i\)號點的子樹中從小到大選擇,直到代價和大於\(M\)。可以使用堆來幫助選擇,復雜度\(O(N^2\cdot \log N)\)。
從下到上考慮,在\(i\)號節點所選的點一定是在它的兒子節點中選的點或者\(i\)號節點,所以只需要將它的兒子中選的點拿出來建堆。同樣可以考慮啟發式合並,復雜度為\(O(N \cdot \log^2N)\)
其實這個是涉及到兩個堆合並的問題,那麽就可以使用可並堆了,而左偏樹是一種高效可並堆,所以使用左偏樹。
轉化一下,對於每個節點維護子樹大根堆,若堆中忍者薪水和大於\(M\),則pop。時間復雜度\(O(N \cdot \log N)\)
代碼
#include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<ctime> #include<iostream> #include<string> #include<vector> #include<list> #include<deque> #include<stack> #include<queue> #include<map> #include<set> #include<bitset> #include<algorithm> #include<complex> #pragma GCC optimize ("O0") using namespace std; template<class T> inline T read(T&x){ T data=0; int w=1; char ch=getchar(); while(!isdigit(ch)) { if(ch==‘-‘) w=-1; ch=getchar(); } while(isdigit(ch)) data=10*data+ch-‘0‘,ch=getchar(); return x=data*w; } typedef long long ll; const int INF=0x7fffffff; const int MAXN=1e5+7; struct Edge { int nx,to; }E[MAXN]; int head[MAXN],ecnt; void addedge(int x,int y) { E[++ecnt].to=y; E[ecnt].nx=head[x],head[x]=ecnt; } int n,m; int c[MAXN],l[MAXN]; int root[MAXN],rcnt,size[MAXN]; ll sum[MAXN],ans; struct LeftTree { int ch[MAXN][2]; int val[MAXN],dis[MAXN]; int merge(int x,int y) { if(x==0||y==0) return x+y; if(val[x]<val[y]) swap(x,y); ch[x][1]=merge(ch[x][1],y); if(dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][0],ch[x][1]); dis[x]=dis[ch[x][1]]+1; return x; } int&top(int x) { return val[x]; } void pop(int&x) { x=merge(ch[x][0],ch[x][1]); } }LT; void dfs(int x) { root[x]=++rcnt; LT.val[rcnt]=c[x]; size[x]=1; sum[x]=c[x]; for(int i=head[x];i;i=E[i].nx) { int y=E[i].to; dfs(y); size[x]+=size[y]; sum[x]+=sum[y]; root[x]=LT.merge(root[x],root[y]); } while(sum[x]>m) { sum[x]-=LT.top(root[x]); LT.pop(root[x]); --size[x]; } ans=max(ans,(ll)size[x]*l[x]); } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); read(n);read(m); for(int i=1;i<=n;++i) { int fa; read(fa); addedge(fa,i); read(c[i]);read(l[i]); } dfs(0); printf("%lld\n",ans); // fclose(stdin); // fclose(stdout); return 0; }
BZOJ2809 [Apio2012]dispatching