Bzoj2809 APIO2012 派遣 主席树经典题

来源:互联网 发布:java onvif协议 编辑:程序博客网 时间:2024/04/24 20:44

这个题。。。。

真的是整死我了。。


首先看哪个领导者

这个是需要枚举的,很简单不解释了


下面分析如果固定一个领导者的求解过程

首先我们注意到ans是人数乘以领导值

而领导值通过枚举已经固定了

那么就是求人数的问题了


那么可以肯定的是每个人对答案的贡献都是一样的,但是他们的薪水不一样

所以有点智商的人都会选哪个薪水小的

所以就是枚举以后的区间k小了


splay显然是可以的 


我为了加深对主席树的理解专门用了主席树

如果不会主席树可以看这里


#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#define MAX 100009#define Max 3800009#define inf 0x7fffffff#define ll long long#define rep(i, j, k) for(int i = j; i <= k; i++)using namespace std;int to[MAX * 2], head[MAX],next[MAX * 2], first[MAX], last[MAX];int DfsColck = 0, dfn[MAX * 2], root, cnt = 0;int tree[MAX], child[Max][2], size[Max], s = 0, tot = 0;int n, rank[MAX], t[MAX * 2];ll sum[Max], m, ans = -inf;int a[MAX][2];struct wbysr{ll v;int t;}b[MAX];inline void add (int x, int y){to[++tot] = y;next[tot] = head[x];head[x] = tot;}bool cmp (wbysr a1, wbysr a2){return a1.v < a2.v;}void dfs (int x){dfn[first[x] = ++DfsColck] = x;for (int i = head[x]; i; i = next[i])dfs (to[i]);dfn[last[x] = ++DfsColck] = x;}inline int build (int l, int r){int Root = ++cnt;tree[Root] = 0;if(l != r){int mid = (l + r) >> 1;child[Root][0] = build (l, mid);child[Root][1] = build (mid + 1, r);}return Root;}int update (int l, int r, int Root, int pos, ll value){int New = ++cnt;size[New] = size[Root] + 1;sum[New] = sum[Root] + value;if (l == r)return New;int mid = (l + r) >> 1;if (pos <= mid)child[New][1] = child[Root][1], child[New][0] = update (l, mid, child[Root][0], pos, value);elsechild[New][0] = child[Root][0], child[New][1] = update (mid+1, r, child[Root][1], pos, value);return New;}inline void debug (){rep (i, 0, DfsColck)printf ("%d %d\n", i, t[i]);}int main(){scanf ("%d%lld", &n, &m);m *= 2;rep (i, 1, n){int x;scanf ("%d%lld%lld", &x, &a[i][0], &a[i][1]);if (x)add (x, i);elseroot = i;b[i].v = a[i][0];b[i].t = i;}b[n + 1].v = -inf, b[n + 1].t = 0;b[s = n + 2].v = inf, b[s].t = 0;sort (b + 1, b + 1 + s, cmp);rep (i, 1, s)rank[ b[i].t ] = i;dfs ( root );t[0] = 0;rep (i, 1, DfsColck)t[i] = update (1, s, t[i - 1], rank[ dfn[i] ], a[ dfn[i] ][0]);//debug ();rep (i, 1, n){ll num = 0, rec = m;int t0 = t[first[i] - 1], t1 = t[last[i]];int l = 1, r = s;while (l < r){ll now = sum[child[t1][0]] - sum[child[t0][0]];int mid = (l + r) >> 1;if (now <= rec){rec -= now;num += size[child[t1][0]] - size[child[t0][0]];t0 = child[t0][1];t1 = child[t1][1];l = mid + 1;}else{t0 = child[t0][0];t1 = child[t1][0];r = mid;}}ans = max (ans, (num / 2) * a[i][1]);}printf ("%lld\n", ans);return 0;}


0 0
原创粉丝点击