题意:给你一个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 }