短い質問が意図されている:に\(\ N-)バイナリ点、
par[i]=i/2
各点が有する\([i]は\)とフルーツ\(m個\)操作、各時間\(uがする\しますV \)(保証\(uが\)される(V \)\以下でフェッチしない)の祖先\(のC \)フルーツ、各貢献取っ\を(ワット\)の利益を
まず暴力の後、費用流側を構築することができます。よる最適化の考慮事項、見かけの貪欲な戦略がある\(W \)可能な限り最大の順は、二部グラフマッチングを決定プラスバイナリすることができます。
ホール定理を考えると、任意のサブセットに相当する\(Sにおける\ {IのSUM _ \} A [I] \ GE \ {u_i SUM _ \でS \&V_I \ S} C_Iで\) 。
もちろん私たちは考慮する必要があり、これは状況Unicom社のブロックです。考えてみましょう\(DP \) OUTに(私は\)\最小限の樹木の根を。
特定されたルートなので、我々はできる(C_I \)\するために割り当てられた\(V_I \)に。
転送は
、[I] [J F [\ [] = \分+ \分(] iは2 + 1 * [F [j]が、0-0)+ valを(0、iは2] [j]を* [F) I] [J] \]
前処理\(N- \ N- \ログ)、およびリンクチェーンブロック最小複雑含む鎖オペレータに挿入\を(N- \ 2N ^を\ログ)。
コード
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
typedef long long ll;
long long f[20][N<<1],g[20][N<<1];
int dep[N],a[N];
int n,m;
ll ans=0;
struct Line{
int u,v,cap,w;
bool operator < (const Line b)const{return w < b.w;}
void read(){scanf("%d%d%d%d",&u,&v,&cap,&w);}
}l[N];
void Main(){
ans=0;
cin >> n >> m;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
dep[i]=dep[i>>1]+1;
for(int j=dep[i];j;j--)g[j][i]=a[i];
}
for(int i=1;i<=dep[n];i++){
for(int j=n;j;j--)f[i][j]=min(0ll,f[i][j<<1|1])+min(0ll,f[i][j<<1])+g[i][j];
}
for(int i=1;i<=m;i++)l[i].read();
sort(l+1,l+m+1);
for(int i=m;i;i--){
int hed=l[i].u;ll Mn=l[i].cap;
for(;hed;hed>>=1){
int d=dep[hed],nxt=l[i].v,lst=0;ll ths=0;
while(nxt!=(hed>>1)){
ths+=min(0ll,(nxt<<1|1)==lst?0ll:f[d][nxt<<1|1])+min(0ll,(nxt<<1)==lst?0ll:f[d][nxt<<1])+g[d][nxt];
lst=nxt;nxt>>=1;
}
Mn=min(Mn, ths);
}
ans+=l[i].w*Mn;
hed=l[i].u;
for(;hed;hed>>=1){
int nxt=l[i].v,d=dep[hed];
g[d][nxt]-=Mn;
for(;nxt;nxt>>=1){
f[d][nxt]=min(0ll,f[d][nxt<<1])+min(0ll,f[d][nxt<<1|1])+g[d][nxt];
}
}
}
for(int d=1;d<=dep[n];d++)for(int i=1;i<=n;i++)f[d][i]=g[d][i]=0;
cout << ans << endl;
}
int main()
{
int T;cin >> T;
while(T--){
Main();
}
return 0;
}