题目:
https://vjudge.net/problem/CodeForces-785E
题意:
给定一个初始为
1到n
的长度为
n
的序列,有
思路:
分块。交换 x y ,只会影响 [x+1,y−1] 内的元素,然后就可以统计了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200000 + 10, INF = 0x3f3f3f3f;
int L[N], R[N], pos[N];
int sz, block;
int a[N], b[N];
void reset(int x)
{
for(int i = L[x]; i <= R[x]; i++) b[i] = a[i];
sort(b + L[x], b + 1 + R[x]);
}
void init(int n)
{
block = (int)sqrt(n);
sz = n / block;
if(n % block) sz++;
for(int i = 1; i <= n; i++) pos[i] = (i-1) / block + 1;
for(int i = 1; i <= sz; i++)
{
L[i] = (i-1) * block + 1;
R[i] = i * block;
}
R[sz] = n;
for(int i = 1; i <= sz; i++) reset(i);
}
//void update(int x, int y)//偷懒可以直接排序
//{
// swap(a[x], a[y]);
// reset(pos[x]);
// reset(pos[y]);
//}
void update(int x, int y)
{
int xb = pos[x], yb = pos[y];
int id = lower_bound(b + L[xb], b + 1 + R[xb], a[x]) - b;
b[id] = a[y];
for(int i = id; pos[i] == pos[i-1] && b[i] < b[i-1]; i--) swap(b[i], b[i-1]);
for(int i = id; pos[i] == pos[i+1] && b[i] > b[i+1]; i++) swap(b[i], b[i+1]);
id = lower_bound(b + L[yb], b + 1 + R[yb], a[y]) - b;
b[id] = a[x];
for(int i = id; pos[i] == pos[i-1] && b[i] < b[i-1]; i--) swap(b[i], b[i-1]);
for(int i = id; pos[i] == pos[i+1] && b[i] > b[i+1]; i++) swap(b[i], b[i+1]);
swap(a[x], a[y]);
}
int query(int l, int r, int val)
{
if(l > r) return 0;
int lb = pos[l], rb = pos[r];
int ans = 0;
if(lb == rb)
{
for(int i = l; i <= r; i++)
if(a[i] < val) ans++;
return ans;
}
else
{
for(int i = l; i <= R[lb]; i++)
if(a[i] < val) ans++;
for(int i = L[rb]; i <= r; i++)
if(a[i] < val) ans++;
for(int i = lb+1; i < rb; i++)
ans += upper_bound(b + L[i], b + 1 + R[i], val) - (b + L[i]);
return ans;
}
}
int main()
{
int n, m;
while(~ scanf("%d%d", &n, &m))
{
for(int i = 1; i <= n; i++) a[i] = i;
init(n);
int x, y;
ll ans = 0;
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
if(x == y) printf("%lld\n", ans);
else
{
if(x > y) swap(x, y);
//query(x+1,y-1,a[x])是原本区间[x+1,y-1]和a[x]成逆序数对的数量,是即将损失的,y-x-1-query(x+1,y-1,a[x])是新得到的逆序数对
ans += y - x - 1 - 2*query(x+1, y-1, a[x]);
//和上面一反
ans -= y - x - 1 - 2*query(x+1, y-1, a[y]);
if(a[x] < a[y]) ans++;
else ans--;
printf("%lld\n", ans);
update(x, y);
}
}
}
return 0;
}