• 牛客暑假多校第五场 D inv


    题意:给你一个n, 接来下给你一个 [1,n] 中偶数的排列, 还有一个 [1, n] 中 奇数 按照递增的顺序排列, 现在求一个原数列, 使得偶数列排序 和 奇数列 都是原数列的一个子序列, 现在求原数列的最小的逆序对是多少。

    题解:

    昨天一直想的是把偶数列往奇数列里面插入, 又想到这个东西有一定的单调性, 但是不好处理。

    现在我们转换思路, 将奇数列往偶数列中插入, 对于这种写法来说, 你递增的 2i+1 的最优位置一定也是递增的。

    假设我们现在知道了 2k+1 对于每一个插入位置产生的逆序对是多少, 那么当我们处理到 2(k+1) + 1 的数的时候,我们可以发现,所有在 2(k+1) 这个数的位置前面的所有可以插入数的位置他们的逆序对数都会+1,所有在 2*(k+1) 的位置后面的所有的可插入的数的位置会产生的逆序对数都会 -1。

    所以当我们从1 -> n 处理奇数的时候 每次处理完一个奇数 2*i + 1之后都会在 [1,  pos(2*(i+1)) ] 这一段的位置产生的逆序对数 + 1, [pos(2*(i+1)) + 1, end] 这一段位置的产生的逆序对数 -1 。

    这样就说明了最优位置也是随着 i 增大而增大的。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
     4 #define LL long long
     5 #define ULL unsigned LL
     6 #define fi first
     7 #define se second
     8 #define pb push_back
     9 #define lson l,m,rt<<1
    10 #define rson m+1,r,rt<<1|1
    11 #define max3(a,b,c) max(a,max(b,c))
    12 #define min3(a,b,c) min(a,min(b,c))
    13 typedef pair<int,int> pll;
    14 const int inf = 0x3f3f3f3f;
    15 const LL INF = 0x3f3f3f3f3f3f3f3f;
    16 const LL mod =  (int)1e9+7;
    17 const int N = 2e5 + 100;
    18 int n;
    19 int c[N], b[N], tree[N];
    20 int lazy[N<<2], mn[N<<2];
    21 map<int,int> mp;
    22 void add(int x, int c){
    23     while(x <= n){
    24         tree[x] += c;
    25         x += x&(-x);
    26     }
    27 }
    28 int query(int x){
    29     int ret = 0;
    30     while(x){
    31         ret += tree[x];
    32         x -= x&(-x);
    33     }
    34     return ret;
    35 }
    36 inline void Push_Up(int x){
    37     mn[x] = min(mn[x<<1|1], mn[x<<1]);
    38 }
    39 inline void Push_Down(int x){
    40     if(lazy[x]){
    41         mn[x<<1] += lazy[x];
    42         mn[x<<1|1] += lazy[x];
    43         lazy[x<<1] += lazy[x];
    44         lazy[x<<1|1] += lazy[x];
    45         lazy[x] = 0;
    46     }
    47 }
    48 void Update(int l, int r, int rt, int L, int R, int c){
    49     if(L <= l && r <= R){
    50         lazy[rt] += c;
    51         mn[rt] += c;
    52         return ;
    53     }
    54     int m = l + r >> 1;
    55     Push_Down(rt);
    56     if(L <= m) Update(lson, L, R, c);
    57     if(m < R) Update(rson, L, R, c);
    58     Push_Up(rt);
    59 }
    60 void build(int l, int r, int rt){
    61     lazy[rt] = 0;
    62     if(l == r){
    63         mn[rt] = c[l];
    64         return;
    65     }
    66     int m = l+r >> 1;
    67     build(lson);
    68     build(rson);
    69     Push_Up(rt);
    70 }
    71 int main(){
    72     scanf("%d", &n);
    73     int m = n/2;
    74     LL ans = 0;
    75     for(int i = 1; i <= m; i++){
    76         scanf("%d", &b[i]);
    77         mp[b[i]] = i;
    78         add(b[i], 1);
    79         ans += i - query(b[i]);
    80     }
    81     int t = m + 1;
    82     for(int i = 1; i <= t; i++)
    83         c[i] = i - 1;
    84     build(1, t, 1);
    85     for(int i = 3; i <= n; i += 2){
    86         int p = mp[i-1];
    87         Update(1, t, 1, 1, p, 1);
    88         Update(1, t, 1, p+1, t, -1);
    89         ans += mn[1];
    90     }
    91     printf("%lld
    ", ans);
    92     return 0;
    93 }
    View Code
  • 相关阅读:
    服务器端渲染和客户端渲染
    混沌开窍---24幅由算法生成的正方形图像
    三生万物---算法生成的25幅三角形图像
    九尾之火---算法生成的动画图像
    最简单的分形图像生成算法
    正与邪---25幅由算法生成的五角星图像
    一幅画<十六芒星盾>---程序员or艺术家
    火火火---12幅算法生成火的图像
    恶魔的指纹---49幅由算法生成的七芒星图像
    混沌分形之电子云
  • 原文地址:https://www.cnblogs.com/MingSD/p/9413809.html
Copyright © 2020-2023  润新知