# [sorting] [dichotomy] [dp]JZOJ 2747 gold picking

Description

Once upon a time, there was a maze. The shape of the maze was like a tree with roots. Each node (except for the leaf node) had exactly K sons.
At the beginning, you are at the root node. The K sons of the root node are marked as' A ',' B ',' C ' , and the K son nodes of node 'A' are marked as' AA ',' AB ',' AC ' , and so on. This tree has A total of L layers.
Now you know in advance that there is gold in M nodes, and you can send N robots to collect gold. First of all, you can specify the target nodes of each robot, so these robots will collect all the gold from the root node to the target node (including the target node), but the gold at each location can only be collected once.
Now you need to work out a goal allocation plan to get the most gold.

Title Solution

```First, we rank m nodes from small to large
So we need to make trees, in fact, we only need to connect these gold nodes together
We found 2~m's father (or grandfather or great grandfather or great grandfather or great grandfather...) (use!! Two points!! Implementation), stored in the queue
At last, dp
Let's take f[i][j] as the root of the ith node, and use the j-th robot to collect the maximum number of gold
The equation of state transition is f[x][i]=max(f[x][i],f[x][i-j]+f[y][j])
(Ps: x is the current node, i is the currently enumerated robot, y is the next generation node, j is the next generation node)
```

Code

```uses math;
type strx=string;
var     num,m,k,l,n,x,i,j:longint;
next,last,first,bz:array[0..50050]of longint;
a:array[0..50050]of strx;
f:array[0..50050,0..50]of longint;
w:string;

procedure insert(i,j:longint);
begin
inc(num);
next[num]:=last[i];
last[i]:=num;
first[num]:=j;
end;

procedure qsort(l,r:longint);
var     i,j:longint;
mid,t:strx;
begin
if (l>=r) then exit;
i:=l; j:=r; mid:=a[(l+r) div 2];
repeat
while (a[i]<mid) do inc(i);
while (a[j]>mid) do dec(j);
if (i<=j) then
begin
t:=a[i]; a[i]:=a[j]; a[j]:=t;
inc(i); dec(j);
end;
until i>j;
qsort(l,j);
qsort(i,r);
end;

function find(x:strx):longint;
var     l,r,mid:longint;
begin
l:=1; r:=i;
while (l<r) do
begin
mid:=(l+r)div 2;
if (a[mid]<x)then l:=mid+1 else r:=mid;
end;
if (a[l]<>x) then exit(0) else exit(l);
end;

procedure dp(x:longint);
var     k,y,i,j:longint;
begin
k:=last[x];
while (k<>0) do
begin
y:=first[k];
dp(y);
for i:=n downto 1 do
for j:=1 to i do
f[x,i]:=max(f[x,i],f[y,j]+f[x,i-j]);
k:=next[k];
end;
for i:=1 to n do f[x,i]:=f[x,i]+bz[x];
end;

begin
for i:=1 to m do readln(a[i]);
inc(m);
a[m]:='';
qsort(1,m);
x:=1;
for i:=2 to m do
begin
w:=a[i];
delete(w,length(w),1);
j:=find(w);
while (j=0) do
begin
delete(w,length(w),1);
j:=find(w);
end;
insert(j,i);
bz[i]:=1;
end;
dp(1);
writeln(f[1,n]);
end.
```

Posted by Dan911 on Thu, 30 Apr 2020 05:56:57 -0700