Codeforces Round #751 (Div. 2)E. Optimal Insertion(结论,分治)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #751 (Div. 2)E. Optimal Insertion(结论,分治)相关的知识,希望对你有一定的参考价值。
结论一
对 b b b排序,设 b i b_i bi放在 a p i a_{p_i} api的前面,那么最优策略下可以是
p 1 < p 2 < p 3 . . . . . . p_1<p_2<p_3...... p1<p2<p3......的一组解
可以反证,如果最有策略不满足上式,也就是存在 i , j i,j i,j满足 b i < b j & & p i > p j b_i<b_j\\&\\&p_i>p_j bi<bj&&pi>pj
那么对于 a a a数组来说,由在于 [ 1 , p j − 1 ] [1,p_j-1] [1,pj−1]和 [ p i , n ] [p_i,n] [pi,n]的元素和 b i , b j b_i,b_j bi,bj的相对位置没变不需要考虑
而如果我们交换 b i , b j b_i,b_j bi,bj,显然 a [ p j . . . . . . . . p i − 1 ] a[p_j........p_i-1] a[pj........pi−1]和 b i , b j b_i,b_j bi,bj形成的逆序变少,证毕.
结论二
对于 b i < b j b_i<b_j bi<bj,若使 b i b_i bi取到最优位置 p i p_i pi, b j b_j bj取到最优位置 p j p_j pj,满足 p j > p i p_j>p_i pj>pi
也就是对于每个 b i b_i bi找到自身最优的放置位置即可
暴力找是 O ( n m ) O(nm) O(nm)的,考虑分治法
先找 b m i d b_{mid} bmid的位置 p m i d p_{mid} pmid,然后分成 [ 1 , p m i d ] [1,p_{mid}] [1,pmid]和 [ p m i d + 1 , n + 1 ] [p_{mid+1},n+1] [pmid+1,n+1]递归找
#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e6+10;
int n,m,a[maxn],b[maxn];
vector<int>vec,w[maxn];
int siz,sum[maxn];
int lowbit(int x){return x&(-x);}
void add(int x){for( ; x<=siz ; x+=lowbit(x)) sum[x]++; }
int ask(int x){
int ans = 0;
for( ; x ; x-=lowbit(x)) ans += sum[x];
return ans;
}
void solve(int l,int r,int L,int R)
{
if( l>r ) return;
int mid = (l+r>>1), inv = 0, mi = 0, id = L;
for(int i=L+1;i<=R;i++)//放在a[i]的后面
{
inv += ( a[i]>b[mid] )?1:( a[i]<b[mid]?-1:0 );
if( inv<mi ) mi = inv, id = i;
}
w[id].push_back( mid );
solve(l,mid-1,L,id ); solve( mid+1,r,id,R );
}
int main()
{
int t; cin >> t;
while( t-- )
{
cin >> n >> m;
for(int i=1;i<=n;i++) scanf("%d",&a[i] ),vec.push_back( a[i] );
for(int i=1;i<=m;i++) scanf("%d",&b[i] ),vec.push_back( b[i] );
sort( b+1,b+1+m ); sort( vec.begin(),vec.end() );
solve( 1,m,0,n );
vec.erase( unique( vec.begin(),vec.end() ), vec.end() );
siz = vec.size();
for(int i=0;i<=2*siz;i++) sum[i] = 0;
for(int i=1;i<=n;i++) a[i] = lower_bound( vec.begin(),vec.end(),a[i] )-vec.begin()+1;
for(int i=1;i<=m;i++) b[i] = lower_bound( vec.begin(),vec.end(),b[i] )-vec.begin()+1;
long long ans = 0;
for(int i = n; i>=0; i--)
{
for(auto v:w[i] ) ans += ask( b[v]-1 );
for(auto v:w[i] ) add( b[v] );
if( i ) ans += ask( a[i]-1 ), add( a[i] );
}
printf("%lld\\n",ans );
vec.clear();
for(int i=0;i<=n+1;i++) w[i].clear();
}
}
以上是关于Codeforces Round #751 (Div. 2)E. Optimal Insertion(结论,分治)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #751 (Div. 2) ABCD
Codeforces Round #751 (Div. 1) B
Codeforces Round #751 (Div. 1) A
Codeforces Round #751 (Div. 2)E. Optimal Insertion(结论,分治)