F. Easy Fix

题意:
给定一个长度为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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include //io控制头文件 cout<
#include       
//#pragma GCC optimize(2)
#define ms(x,n) memset(x,n,sizeof x)
#define endl '\n'
#define pii pair 
#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  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  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 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 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

*/

你可能感兴趣的:(算法)