CF1615H Reindeer Games (L_1保序回归模版)
CF1615H Reindeer Games (\(L_1\)保序回归模版)
\(L_1\)保序回归用到了几个重要引理:
- 答案\(\in\{a_1,a_2,a_3...a_n\}\)。
- 答案在一定程度上可以二分。也就是说知道哪些答案\(\geq x\)。
首先第一个结论是显然的,不然一定可以调整且不使得答案变劣。
对于第二个结论,如果满足\(a_i\not\in (l,r)\),那么可以如果答案只取\(\set{l,r}\),则和最优答案的大小关系不变。
这样就可以整体二分了。
int a[1001];
vector<mp> edge;
int answer[1001];
vector<int> b;
int ans[1001];
bool in[GRAPH_SIZE];
void tour(int now){
in[now]=1;
for(auto it:each[now]){
if(e[it].c&&!in[e[it].v]){
tour(e[it].v);
}
}
}
void solve(vector<int> v,int l,int r){
if(l==r||v.empty()){
for(auto it:v)
ans[it]=b[l];
return ;
}
memset(in,0,sizeof(in));
for(auto it:v) in[it]=1;
init();
int mid=(l+r)/2;
for(auto it:v){
make_edge(s,it,(LL)(1e13)+abs(b[mid+1]-a[it]));
make_edge(it,t,(LL)(1e13)+abs(b[mid]-a[it]));
}
for(auto it:edge){
int u,v;
tie(u,v)=it;
if(in[u]&&in[v]) make_edge(v,u,INF);
}
Dinic();
memset(in,0,sizeof(in));
tour(s);
vector<int> L,R;
for(auto it:e){
int u,v;
u=it.u;
v=it.v;
if(in[u]&&!in[v]){
if(u==s){
R.PB(v);
}
if(v==t){
L.PB(u);
}
}
}
sort(ALL(L));
L.erase(unique(ALL(L)),L.end());
sort(ALL(R));
R.erase(unique(ALL(R)),R.end());
solve(L,l,mid);
solve(R,mid+1,r);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin>>n>>m;
rb(i,1,n) cin>>a[i];
rb(i,1,m){
int u,v;
cin>>u>>v;
edge.PB(II(u,v));
}
rb(i,1,n) b.PB(a[i]);
sort(ALL(b));
b.erase(unique(ALL(b)),b.end());
vector<int> v;
rb(i,1,n) v.PB(i);
solve(v,0,b.size()-1);
rb(i,1,n) cout<<ans[i]<<" ";
cout<<endl;
return 0;
}

浙公网安备 33010602011771号