luogu P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I

https://www.luogu.com.cn/problem/P5046

区间逆序对,强制在线,吼哇
如果离线就是二次离线莫队

思路倒是不难,就是卡常严重QWQ
不过确实是我有个地方写丑了

预处理几个东西

  • a n s L [ i ] [ j ] 表 示 [ L [ i ] , j ] 的 答 案 , ( 第 i 块 的 左 端 点 到 j 的 答 案 ) ansL[i][j]表示 [L[i],j]的答案,(第i块的左端点到j的答案) ansL[i][j][L[i],j]ij
  • a n s R [ i ] [ j ] 表 示 [ j , R [ i ] ] 的 答 案 ansR[i][j]表示[j,R[i]]的答案 ansR[i][j][j,R[i]]

如果不考虑左右散块之间的贡献,显然可以得到是
加起来减去中间的(红+蓝-黑)
在这里插入图片描述

然后考虑散块怎么做
很简单,直接预先排好序,归并起来即可

代码实现不算复杂,注意卡常(交前洗把脸)

code:

#include<bits/stdc++.h>
#define N 100005
#define M 325
#define ll long long
using namespace std;
int read() {
    int x = 0;
    char ch = getchar();
    for(; ch < '0' || ch > '9'; ) ch = getchar();
    for(; ch >= '0' && ch <= '9'; ) x = (x << 3) + (x << 1) + (ch - 48), ch = getchar();
    return x;
}
struct A {
    int x, id;
} b[N];
int cmp(A x, A y) {
    return x.x < y.x;
}
int x[N], y[N], cx, cy, a[N], pre[N], suf[N], s1[M][N], s2[M][N], n, m, blo, bel[N], sp[N], gs[N];
#define lowbit(x) (x & -x)
int t[N];
void update(int x, int y) {
    for(; x <= n; x += lowbit(x)) t[x] += y;
}
int query(int x) {
    int ret = 0;
    for(; x; x -= lowbit(x)) ret += t[x];
    return ret;
}
ll *ansL[M], *ansR[M], B[N * M * 3 / 2], *now = B;
int merge() {
    int i = 1, j = 1, ret = 0;
    for(; i <= cx && j <= cy; ) {
        if(x[i] < y[j]) i ++;
        else ret += cx - i + 1, j ++;
    }
    return ret;
}
int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; i ++) a[i] = read(), b[i].x = a[i], b[i].id = i;
    blo = min(550, n);
    //blo = sqrt(n) + 1;
    for(int i = 1; i <= n; i ++) bel[i] = (i - 1) / blo + 1;
    for(int id = 1; id <= bel[n]; id ++) {
        int l = (id - 1) * blo + 1, r = min(id * blo, n);
        sort(b + l, b + r + 1, cmp);
        for(int i = l; i <= r; i ++) update(a[i], 1), pre[i] = i - l + 1 - query(a[i]);
        for(int i = l; i <= r; i ++) update(a[i], - 1);
        for(int i = r; i >= l; i --) update(a[i], 1), suf[i] = query(a[i] - 1);
        for(int i = l; i <= r; i ++) update(a[i], - 1);
        sp[l] = pre[l];
        for(int i = l + 1; i <= r; i ++) sp[i] = sp[i - 1] + pre[i];
    }
    
    for(int i = 1; i <= bel[n]; i ++) {
        int l = (i - 1) * blo + 1, r = min(i * blo, n);
        for(int j = l; j <= r; j ++) gs[a[j]] ++;
        for(int j = 1; j <= n; j ++) s1[i][j] = s1[i][j - 1] + gs[j];
        for(int j = n; j >= 1; j --) s2[i][j] = s2[i][j + 1] + gs[j];
    }
    
    for(int i = 1; i <= bel[n]; i ++) {
        int l = (i - 1) * blo + 1, r = min(i * blo, n);
        //ansL[i].resize(n - l + 2);
        ansL[i] = now; now += n - l + 2;
        int py = l - 1;
        for(int j = l; j <= n; j ++) ansL[i][j - py] = ansL[i][j - 1 - py] + (s2[bel[j] - 1][a[j] + 1] - s2[i - 1][a[j] + 1]) + pre[j];
        //ansR[i].resize(r + 2);
        ansR[i] = now; now += r + 2;
        for(int j = r; j >= 1; j --) ansR[i][j] = ansR[i][j + 1] + (s1[i][a[j] - 1] - s1[bel[j]][a[j] - 1]) + suf[j];
    }
    
    ll lst = 0;
    for(; m --; ) {
        int l, r;
        l = read(), r = read();
        l ^= lst, r ^= lst; if(l > r) swap(l, r); lst = 0;
        ll s = 0;
        cx = cy = 0;
        int L = (bel[l] - 1) * blo + 1, R = min(n, bel[r] * blo);
        if(bel[l] == bel[r]) {
            for(int i = L; i <= R; i ++) {
                if(b[i].id < l) lst -= s;
                s += (l <= b[i].id && b[i].id <= r);
            }
            lst += sp[r] - (l == L? 0 : sp[l - 1]);
            printf("%lld\n",lst);
        } else {
            int py = bel[l] * blo;
            lst = ansL[bel[l] + 1][r - py] + ansR[bel[r] - 1][l] - ansL[bel[l] + 1][(bel[r] - 1) * blo - py];
            int szl = bel[l] * blo;
            for(int i = L, j = (bel[r] - 1) * blo + 1; j <= R && i <= szl; j ++) {
                for( ; b[i].x < b[j].x && i <= szl; ) s += b[i].id >= l, i ++;
                lst += (b[j].id <= r) * (szl - l + 1 - s);
            }
          //  for(int i = L; i <= bel[l] * blo; i ++) if(b[i].id >= l) x[++ cx] = b[i].x;
           // for(int i = (bel[r] - 1) * blo + 1; i <= R; i ++) if(b[i].id <= r) y[++ cy] = b[i].x;
            //lst += merge();
            printf("%lld\n", lst);
        }
    }
    return 0;
}
posted @ 2021-09-02 20:50  lahlah  阅读(26)  评论(0编辑  收藏  举报