您的位置:首页 > 其它

Bzoj2809 APIO2012 派遣 主席树经典题

2014-04-21 18:27 197 查看
这个题。。。。

真的是整死我了。。

首先看哪个领导者

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

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

首先我们注意到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);
else
child[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);
else
root = 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: