Codeforces Round #751 (Div. 2)E. Optimal Insertion(结论,分治)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #751 (Div. 2)E. Optimal Insertion(结论,分治)相关的知识,希望对你有一定的参考价值。

Link

结论一

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,pj1] [ 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........pi1] 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(结论,分治)

Codeforces Round #751 (Div. 2)E. Optimal Insertion(结论,分治)

Codeforces Round #751 (Div. 2)D. Frog Traveler