BZOJ2809 dispatching
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2809
知识点: 可持久化线段树、DFS序
解题思路:
先根据给出的树处理出每一点的\(DFS\)序,记录每一棵子树的最小(\(Le\))、最大(\(Ri\)) \(DFS\)序。先建一棵空的权值线段树(从小到大),然后根据\(DFS\)序可持久化更新线段树。查询答案的时候枚举每一个点,查询以这一点为根的子树对应的第\(Le\)个和第\(Ri\)版本之间的线段树,尽量多取点,取到\(M\)预算不够为止,答案就是取的点数乘根点对应的领导力的最大值。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 100000+5; 5 6 int fa[maxn]; 7 vector<int> G[maxn]; 8 struct poi{ 9 int id; 10 ll cost; 11 }per[maxn]; 12 bool cmp(const poi &a,const poi &b){ 13 return a.cost<b.cost; 14 } 15 int pos[maxn]; 16 ll lin[maxn]; 17 18 int tot=0; 19 int T[maxn*30],lson[maxn*30],rson[maxn*30]; 20 int siz[maxn*30]; 21 ll sum[maxn*30]; 22 23 int dfsxu[maxn],redfsxu[maxn]; 24 int le[maxn],ri[maxn]; 25 int temp=0; 26 void build(int l, int r, int &rt) { 27 rt = ++tot; 28 sum[rt] = 0LL; 29 siz[rt] = 0; 30 if (l == r) return; 31 int m = (l + r) >> 1; 32 build(l, m, lson[rt]); build(m + 1, r, rson[rt]); 33 } 34 void update(int last, int pos, int l, int r, int &rt) { 35 rt = ++tot; 36 lson[rt] = lson[last]; 37 rson[rt] = rson[last]; 38 siz[rt] = siz[last] + 1; 39 sum[rt] = sum[last] + per[pos].cost; 40 if (l == r) return; 41 int m = (l + r) >> 1; 42 if (pos <= m) update(lson[last], pos, l, m, lson[rt]); 43 else update(rson[last], pos, m + 1, r, rson[rt]); 44 } 45 int query(int s, int t, ll maxc, int l, int r) { 46 if (l == r){ 47 if(sum[t]-sum[s]<=maxc) 48 return siz[t]-siz[s]; 49 return 0; 50 } 51 int m = (l + r) >> 1; 52 ll tmp = sum[lson[t]] - sum[lson[s]]; 53 int ret; 54 if (maxc <= tmp) ret = query(lson[s], lson[t], maxc, l, m); 55 else ret = siz[lson[t]]-siz[lson[s]]+query(rson[s], rson[t], maxc - tmp, m + 1, r); 56 return ret; 57 } 58 void dfs(int rt){ 59 redfsxu[rt]=temp; 60 dfsxu[temp]=rt,le[rt]=temp; 61 temp++; 62 for(int i=0;i<G[rt].size();i++) 63 dfs(G[rt][i]); 64 ri[rt]=temp-1; 65 } 66 67 int main(){ 68 int N; 69 ll M; 70 scanf("%d%lld",&N,&M); 71 for(int i=1;i<=N;i++){ 72 scanf("%d%lld%lld",&fa[i],&per[i].cost,&lin[i]); 73 per[i].id=i; 74 G[fa[i]].push_back(i); 75 } 76 sort(per+1,per+1+N,cmp); 77 for(int i=1;i<=N;i++) 78 pos[per[i].id]=i; 79 dfs(0); 80 build(1,N,T[0]); 81 82 for(int i=1;i<=N;i++){ 83 int now=dfsxu[i]; 84 update(T[i-1],pos[now],1,N,T[i]); 85 } 86 ll ans=0; 87 for(int i=1;i<=N;i++){ 88 int ret=query(T[le[i]-1],T[ri[i]],M,1,N); 89 ans=max(ans,lin[i]*(ll)ret); 90 } 91 printf("%lld\n",ans); 92 93 return 0; 94 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”