题目链接
该题是由分块做的,蒟蒻也只能用分块去做了,树套树代码太长了啊呜呜呜。
首先我们先对逆序对做一个分析,课本(线性代数工程学,同济大学) 说,对于n个不同的元素,先规定个元素之间有以一个标准次序(例如n个不同的自然数,可规定由小到大为标准次序), 于是在这n个元素的任意排列中,当某一对元素的先后次序与标准次序不同时,就说它构成1个逆序,一个排列中所有逆序的总数叫做这个排列的逆序数。
然后我们进行的在线操作时交换任意两个元素,首先我们进行分析, 这两个元素的下标如果为x , y的话,我们其实对于[1 , x- 1] , [y + 1 , n]这两个区间是没有任何影响的,可以自己模拟一遍,而对其内部来说我们需要考虑内部与两个元素之间的关系。
分块的细节操作正在更新ing
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std ;
const int N = 1e5 + 10 ;
int read()
{
int res = 0 , flag = 1 ;
char c = getchar() ;
while(!isdigit(c))
{
if(c == '-') flag = -1 ;
c = getchar() ;
}
while(isdigit(c))
{
res = (res << 1) + (res << 3) + (c ^ 48) ;
c = getchar() ;
}
return res * flag ;
}
int n , m , t , ans = 0 ;
int len , pos[N] , L[N] , R[N] ;
int a[N] , b[N] , tmp[N] ;
int get(int x)
{
return x / len ;
}
void maintain(int t)
{
for(int i = L[t] ; i <= R[t] ; i ++)
b[i] = a[i] ;
sort(b + L[t] , b + R[t] + 1) ;
}
void init()
{
memset(L , 0x3f, sizeof L) ;
for(int i = 1 ; i <= n ; i ++)
{
pos[i] = get(i) ;
t = pos[i] ;
L[pos[i]] = min(L[pos[i]] , i) ;
R[pos[i]] = max(R[pos[i]] , i) ;
}
for(int i = 1 ; i <= t ; i ++)
maintain(t) ;
}
void mergesort(int l , int r)
{
if(l >= r) return ;
int mid = l + r >> 1 ;
mergesort(l , mid) ;
mergesort(mid + 1 , r) ;
int i = l , j = mid + 1 ;
int cnt = 0 ;
while(i <= mid && j <= r)
{
if(b[i] <= b[j]) tmp[++ cnt] = b[i ++] ;
else tmp[++ cnt] = b[j ++] , ans += mid - i + 1 ;
}
while(i <= mid)
tmp[++ cnt] = b[i ++] ;
while(j <= r)
tmp[++ cnt] = b[j ++] ;
for(int i = 1 ; i <= cnt; i ++)
b[l + i - 1] = tmp[i] ;
}
int query(int l , int r , int val)
{
int res = 0 ;
if(l > r) return 0 ;
if(pos[l] == pos[r])
{
for(int i = l ; i <= r ; i ++)
if(a[i] > val)
res ++ ;
return res ;
}
for(int i = l ; i <= R[pos[l]] ; i ++)
if(a[i] > val)
res ++ ;
for(int j = r ; j >= L[pos[r]] ; j --)
if(a[j] > val)
res ++ ;
for(int i = pos[l] + 1 ; i <= pos[r] - 1 ; i ++)
res += R[i] - (lower_bound(b + L[i] , b + R[i] + 1 , val + 1) - b) + 1 ;
return res ;
}
int main(void)
{
n = read();
len = sqrt(n) ;
for(int i = 1 ; i <= n ; i ++)
a[i] = read() ;
for(int i = 1 ; i <= n ; i ++)
b[i] = a[i] ;
mergesort(1 , n) ;
printf("%d\n" , ans) ;
init() ;
m = read() ;
for(int i = 1 ; i <= m ; i ++)
{
int x , y ;
x = read() , y = read() ;
int ans_a = query(x + 1 , y - 1 , a[x]) ;
int ans_b = query(x + 1 , y - 1 , a[y]) ;
// cout << ans_a << " " << ans_b << endl ;
// cout << (a - n + a) + (n - b - b) << endl ;
ans += 2 * ans_a - 2 * ans_b ;
if(a[x] < a[y]) ans ++ ;
else ans -- ;
printf("%d\n" , ans) ;
swap(a[x] , a[y]) ;
maintain(pos[x]) ;
if(pos[x] != pos[y])
maintain(pos[y]) ;
}
}