牛客暑假多校第五场 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\n", ans);
92     return 0;
93 }
View Code

 

posted @ 2018-08-03 14:03  Schenker  阅读(228)  评论(0编辑  收藏  举报