题解:P17210 【模板】半在线决策单调性
简化 LARSCH 算法,简单易懂还很好写。
这里假定你已经知道一些基本的决策单调性术语。
显然有
这个东西的正确性是显然的。且这个东西是
因为这个东西的第二步和第四步对于每个
但是这个
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+5;
int n,a[N],b[N];
int f[N],op[N];
struct node{
int c[N],res;
int L=1,R;
void add(int x){
x=a[x];
res+=c[x];
c[x]++;
}
void del(int x){
x=a[x];
c[x]--;
res-=c[x];
}
int w(int l,int r){
while(R<r) add(++R);
while(L>l) add(--L);
while(L<l) del(L++);
while(R>r) del(R--);
return f[l-1]+res+b[r];
}
void chk(int j,int i){
if(w(j,i)<f[i]){
f[i]=w(j,i);
op[i]=j;
}
}
}n1,n2;
void calc(int l,int r){
if(l+1>=r){
n2.chk(r,r);
return;
}
int mid=l+r>>1;
for(int i=op[l];i<=op[r];i++) n1.chk(i,mid);
calc(l,mid);
for(int i=l+1;i<=mid;i++) n1.chk(i,r);
calc(mid,r);
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
fill(f+1,f+n+1,1e18);
n1.chk(1,1),n1.chk(1,n);
calc(1,n);
for(int i=1;i<=n;i++) cout<<f[i]<<' ';
return 0;
}