题解:P11673 [USACO25JAN] Median Heap G
Gordon_Song · · 题解
dp 题。
首先先把
现在来分析这一“近似中位数”的特性:不妨设当前节点为
此时,就能自然而然地设出一个 dp 的状态:设 push_down 函数
)。
就这样,我们有了一个
然而,如果考虑
所以我们可以添加一个优化,只在
int n,q;
const int MAXN=2e6+5;
int a[MAXN],c[MAXN];
int p[MAXN],l,now;
int d[MAXN];
vector<int>que[MAXN],poi[MAXN];
ll tox[MAXN],toe[MAXN],tod[MAXN];//tox:文中的 dp1,toe:文中的 dp,tod:文中的 dp2
void push_up(int x){//转移方程
tox[x]=min({tox[x<<1]+(a[x]>now)*c[x],tox[x<<1|1]+(a[x]>now)*c[x],tox[x<<1]+tox[x<<1|1]});
tod[x]=min({tod[x<<1]+(a[x]<now)*c[x],tod[x<<1|1]+(a[x]<now)*c[x],tod[x<<1]+tod[x<<1|1]});
toe[x]=min({min(tox[x<<1]+tod[x<<1|1],tod[x<<1]+tox[x<<1|1])+(a[x]!=now)*c[x],
toe[x<<1]+min((a[x]>now)*c[x]+tod[x<<1|1],(a[x]<now)*c[x]+tox[x<<1|1]),
toe[x<<1|1]+min((a[x]>now)*c[x]+tod[x<<1],(a[x]<now)*c[x]+tox[x<<1])});
}
ll ans[MAXN];
void dfs(int x){
if(x>n){
toe[x]=1e18;
return ;
}
if((x<<1)>n){
toe[x]=(a[x]!=now)*c[x];
tod[x]=(a[x]<now)*c[x];
tox[x]=(a[x]>now)*c[x];
}else{
dfs(x<<1);dfs(x<<1|1);
push_up(x);
}
// printf("%d %d %d %lld %lld %lld\n",x,a[x],c[x],tod[x],tox[x],toe[x]);
}
void pus(int x){
if(!x)return ;
if(x*2>n){
toe[x]=(a[x]!=now)*c[x];
tod[x]=(a[x]<now)*c[x];
tox[x]=(a[x]>now)*c[x];
}else{
push_up(x);
}
pus(x>>1);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&c[i]);
p[++l]=a[i];
}scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d",&d[i]);p[++l]=d[i];
}
//离散化
sort(p+1,p+1+l);
l=unique(p+1,p+1+l)-p-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(p+1,p+1+l,a[i])-p;
poi[a[i]].push_back(i);
}
for(int i=1;i<=q;i++){
d[i]=lower_bound(p+1,p+1+l,d[i])-p;
que[d[i]].push_back(i);
}
dfs(1);
// now=4;
// dfs(1);
for(int i=1;i<=l;i++){
now=i;
// dfs(1);
for(int j=0;j<poi[i-1].size();j++){
pus(poi[i-1][j]);
}
for(int j=0;j<poi[i].size();j++){
pus(poi[i][j]);
}
for(int j=0;j<que[i].size();j++){
ans[que[i][j]]=toe[1];
}
// printf("now=%d:\n",i);
// for(int j=1;j<=n;j++){
// printf("%d %d %d %lld %lld %lld\n",j,a[j],c[j],tox[j],toe[j],tod[j]);
// }
}
for(int i=1;i<=q;i++){
printf("%lld\n",ans[i]);
}
}