题意:
给定一个长度为n的序列(假设序列中第i个数为x,a[i]为[1,i-1]中小于x的数的个数,b[i]为[i+1,n]中小于x的数的个数,c[i]=min(a[i],b[i])),之后给定一个数m,表示接下来有m次操作,每次操作给定两个数l和r,表示将序列中l位置和r位置的数进行交换,求交换完后序列对应的c数组的和,注意,每次操作是独立的。
按贡献容斥即可
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <iomanip>//io控制头文件 cout<<fixed<<setprecision(3)<<ans<<"\n";
//#include <unordered_map>
#include <bitset>
//#pragma GCC optimize(2)
#define ms(x,n) memset(x,n,sizeof x)
#define endl '\n'
#define pii pair<int,int>
#define M(a,b) make_pair(a,b)
#define fi first
#define se second
#define pb push_back
#define __builtin_popcount popcnt1//getcnt
#define db1(x) cerr<<#x<<"="<<(x)<<" "
#define db2(x) cerr<<#x<<"="<<(x)<<"\n"
#define int long long
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll _gcd(ll a, ll b) { return b > 0 ? _gcd(b, a % b) : a; }
int popcnt1(ll x) { int ans = 0;for (int j = 0;j <= 60;j++)if (x & (1ll << j)) ans++;return ans; }
template <typename T> inline void read(T& t) { int f = 0, c = getchar(); t = 0;while (!isdigit(c)) f |= c == '-', c = getchar();while (isdigit(c)) t = t * 10 + c - 48, c = getchar();if (f) t = -t; }
template <typename T> void print(T x) { if (x < 0) x = -x, putchar('-');if (x > 9) print(x / 10);putchar(x % 10 + 48); }
const double pi = acos(-1.0);
const double eps = 1e-7;//有时候精度可能不够
const int inf = 0x3f3f3f3f;
const ll Inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int N = 1e5+10;
const int M = 1e6 + 10;
int n, m, t, k;
int a[N];
struct node {
int val, id, a, b;
}no[N];
struct wen {
int u, v;
}wn[N*2];
struct queri {
int id,x,y,xi,ce;
bool operator <(const queri& c)const {
return x < c.x;
}
};
struct node2 {
int sum;
}no2[N];
void add(int x) {
for (int i = x;i < N;i += i & -i) {
no2[i].sum++;
}
}
int quer2(int x) {
int ans = 0;
for (int i = x;i;i -= i & -i) {
ans += no2[i].sum;
}
return ans;
}
int ans[N*2];
int ans2[N*2][2];
vector<queri> qv[8];
void jia(int i, int q) {
if (q == 1) {
if (no[i].a <= no[i].b) add(no[i].val);
}
else if (q == 2) {
if (no[i].a > no[i].b + 1) add(no[i].val);
}
else if (q == 3) {
if (no[i].a + 1 < no[i].b) add(no[i].val);
}
else if (q == 4) {
if (no[i].a >= no[i].b) add(no[i].val);
}
else {
add(no[i].val);
}
}
void query(vector<queri> v, int q) {
sort(v.begin(), v.end());
for (int i = 1;i < N;i++) no2[i].sum = 0;
int i = 0;
for (int j = 0;j < v.size();j++) {
while (i < v[j].x) {
jia(i + 1, q);i++;
}
if (q == 5) {
ans2[v[j].id][v[j].ce] += quer2(v[j].y) * v[j].xi;
}
else {
ans[v[j].id] += quer2(v[j].y) * v[j].xi;
}
}
}
void add2(int idd, int l1, int r1, int l2, int r2, int idv,int xi) {
qv[idv].push_back(queri{ idd,r1,r2,1*xi }), qv[idv].push_back(queri{ idd,l1 - 1,r2,-1*xi }), qv[idv].push_back(queri{ idd,r1,l2 - 1,-1*xi }), qv[idv].push_back(queri{ idd,l1 - 1,l2-1,1*xi });
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n;
int sum = 0;
for (int i = 1;i <= n;i++) {
cin >> no[i].val;
a[i] = no[i].val;
no[i].id = i;
no[i].a = quer2(no[i].val);
no[i].b = no[i].val - 1 - no[i].a;
add(no[i].val);
sum += min(no[i].a, no[i].b);
}
//db2(sum);
cin >> m;
for (int i = 1,u,v;i <= m;i++) {
cin >> u >> v;
if (u > v) swap(u, v);
wn[i] = wen{ u,v };
if (u == v) {
ans[i] = sum;
}
else {
qv[5].push_back(queri{ i,v,a[u] - 1,1,0 });qv[5].push_back(queri{ i,u,a[u] - 1,-1,0});
qv[5].push_back(queri{ i,v-1,a[v] - 1,1,1 });qv[5].push_back(queri{ i,u - 1,a[v] - 1,-1,1 });
if (a[u] < a[v]) {
add2(i,u+1, v-1, a[u]+1, a[v]-1, 1,-1);
add2(i, u+1, v-1, a[u]+1, a[v]-1, 2,1);
}
else {
add2(i, u+1, v-1, a[v]+1, a[u]-1, 3,1);
add2(i, u+1, v-1, a[v]+1, a[u]-1, 4,-1);
}
}
}
for (int i = 1;i <= 5;i++) {
query(qv[i], i);
}
for (int i = 1;i <= m;i++) {
//db2(ans[i]);
if (wn[i].u == wn[i].v) {
cout << ans[i] << endl;
}
else {
int u = wn[i].u, v = wn[i].v;
int res = sum - (min(no[u].a, no[u].b) + min(no[v].a, no[v].b));
res += min(no[u].a + ans2[i][0], no[u].b - ans2[i][0]) + min(no[v].a - ans2[i][1], no[v].b + ans2[i][1]);
//db1(ans2[i][0]),db1(ans2[i][1]),db2(res);
res += ans[i];
cout << res << endl;
}
}
return 0;
}
/*
5
5 3 1 2 4
3
3 1
2 5
3 3
5
5 3 1 2 4
3
3 1
1 2
3 3
*/