首页 > 其他分享 >P4024 [CTSC2012]统计学家

P4024 [CTSC2012]统计学家

时间:2023-02-03 19:58:49浏览次数:79  
标签:P4024 统计学家 int bmod ans4 aks while CTSC2012 frac

P4024 [CTSC2012]统计学家

洛谷:P4024 [CTSC2012]统计学家

Solution

首先考虑离散化。

rev1 & rev2

发现要么 \(n = 1\),要么 \(m = 1\),相当于对于一个一维数列求区间逆序对数。

由于没有修改操作,考虑将查询离线,离线完了考虑莫队,移动的时候在树状数组上修改即可。

具体地,当左端点向左移动到 \(i\) 时,在树状数组上查询 \(< a_i\) 的数的个数,累加到答案,并将 \(a_i\) 加入树状数组。

当右端点向右移动到 \(i\) 时,在树状数组上查询 \(> a_i\) 的数的个数,累加到答案,并将 \(a_i\) 加入到树状数组。

删除操作同理。要注意加入和删除在对于更新答案和更新树状数组时的顺序。

rev3 & rev4 & rev5 & rev8 & rev9 & rev10

继承树状数组 + 莫队的想法,我们把这种做法拓展到二维。

具体地,对 \(n\) 行维护 \(n\) 个树状数组,对列进行离线莫队。

为方便统计答案,记 \(f[i][j]\) 表示第 \(i\) 行的元素 \(x\) 与第 \(y\) 列的元素之间贡献的答案。这里钦定 \(i < j\),那么需要统计 \(x > y\) 的对,且同时满足列的限制。

不难发现,每次查询的答案即为 \(\sum\limits_{i = 1}^{n}\sum\limits_{j = i}^{n}f_{i, j}\)。

同样地,在加入和删除 一列 元素时,对左端点和右端点分别讨论。

具体地,当左端点向左移动到 \(x\) 时,答案累加 \(\sum\limits_{i = 1}^{n}\sum\limits_{j = i}^{n}\sum\limits_{k}a_{k}<a_{i, x}\),在树状数组上加入 $\forall 1 \le i\le n, a_{i, x} $。

当右端点向右移动到 \(x\) 时,答案累加 \(\sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{i}\sum\limits_{k}a_{k} > a_{i, x}\),在树状数组上加入 \(\forall 1 \le i \le n, a_{i, x}\)。

这样的思想还是挺有趣的:对全局修改树状数组,统计时自行根据限制限定查询范围

设 \(m\) 与 \(Q\) 同级,时间复杂度为 \(O(m\sqrt{m}n^2\log{(nm)} + mn^2)\)。空间上用 vector 优化。

若 \(n > m\),把矩阵翻一下然后交换 \(m, n\) 即可。

挂一下某些数据点的大致运行效率。

rev3: rev4: rev5:

rev8: rev9:

最慢的跑了 \(4min\)。可以接受。

rev10

这里我们先缓一下,引出另一个解决这道题的方法:二维前缀和。

观察数据点 10,发现 \(n, m\) 只有 \(80\),不妨直接记 \(ans[i][j][x][y]\) 表示 \((i, j)\) 到 \((x, y)\) 内的答案。

采用 \(O(n^2m^2)\) 预处理一下即可。

具体地,可以引入另一个四维数组 \(s[i][j][x][y]\),表示 \((i, j)\) 到 \((x, y)\) 内 \(> a_{x, y}\) 的数的数量,四重循环两次,一次倒着预处理 \(s\),一次正着预处理 \(ans\)。

以上的 \((i, j)\) 和 \((x, y)\) 均满足 \(i \le x\) 且 $ j \le y$。

rev6

数据点 6 和数据点 7 都是 \(n , m = 1000\),这意味着级别飙升到 \(10^9\),而且还要带个 \(\log\)。

我们试图用树状数组 + 莫队跑一下数据点 6:

每 \(10s\) 只能处理几十个询问,效率不尽人意。

仔细观察数据点 6,发现矩阵的值居然有递减关系!

这说明所有满足坐标限制的点对都可以贡献到答案中。

二维前缀和预处理一下,很简单。当然每次 \(O(1)\) 直接算好像也可以。

rev7

发现矩阵中只有 \(5\) 和 \(9\) 两种值,那么也是预处理乱搞一下即可(因为答案只与矩阵边长和两个角的值有关,与坐标无关)。

我的做法是根据左上角和右下角的值分 \(4\) 种情况讨论,分别记 \(ans1/ans2/ans3/ans4[x][y]\) 表示边长为 \(x, y\) 的矩阵对应四种情况的值。实际上讨论的时候,我还把每种情况分了两种情况讨论,具体来说是把 \(2 \times 2\) 的矩阵视作一个点来转移。

这个一定要画图分析才来的快。

给两个矩阵方便观察:

5 9 5 9 5 9 5 9 5 9 
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9 
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
5 9 5 9 5 9 5 9 5 9
9 5 9 5 9 5 9 5 9 5
  • 左上角为 \(5\),右下角为 \(5\):参见第一个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。

    • \(i \bmod 2 = 1, j \bmod 2 = 1\):

      单独处理边界:\(ans1[1][x] = ans1[x][1] = \frac{x^2 - 1}{8}\)。

      递推:\(ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + \frac{(i - 1)(j - 1)}{2} + \frac{ij - 1}{2}\)。

    • \(i \bmod 2 = 0, j \bmod 2 = 0\):

      不用单独处理边界。

      递推:\(ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + \frac{(i - 1)(j - 1) - 1}{2} + \frac{ij}{2}\)。

  • 左上角为 \(5\),右下角为 \(9\):参见第一个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。

    • \(i \bmod 2 = 1, j \bmod 2 = 0\):

      单独处理边界:\(ans2[1][x] = \frac{x^2 - 2x}{8}\)。

      递推:\(ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + \frac{i(j - 1) - 1}{2} + \frac{(i - 1)j}{2}\)。

    • \(i \bmod 2 = 0, j \bmod 2 = 1\):

      单独处理边界:\(ans2[x][1] = \frac{x^2 - 2x}{8}\)。

      递推:\(ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + \frac{(i - 1)j - 1}{2} + \frac{i(j - 1)}{2}\)。

  • 左上角为 \(9\),右下角为 \(5\):参见第二个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。

    • \(i \bmod 2 = 1, j \bmod 2 = 0\):

      单独处理边界:\(ans3[1][x] = \frac{x^2 + 2x}{8}\)。

      递推:\(ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + \frac{(i - 1)(j - 1)}{2} + \frac{ij}{2}\)。

    • \(i \bmod 2 = 0, j \bmod 2 = 1\):

      单独处理边界:\(ans3[x][1] = \frac{x^2 + 2x}{8}\)。

      递推:\(ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + \frac{(i - 1)(j - 1)}{2} + \frac{ij}{2}\)。

  • 左上角为 \(9\),右下角为 \(9\):参见第二个矩阵,以 \((1, 1)\) 为左上角,\((i, j)\) 为右下角。

    • \(i \bmod 2 = 1, j \bmod 2 = 1\):

      单独处理边界:\(ans4[1][x] = ans4[x][1] = \frac{x^2 - 1}{8}\)。

      递推:\(ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + \frac{i(j - 1)}{2} + \frac{(i - 1)j}{2}\)。

    • \(i \bmod 2 = 0, j \bmod 2 = 0\):

      不用单独处理边界。

      递推:\(ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + \frac{i(j - 1)}{2} + \frac{(i - 1)j}{2}\)。

Final Code

#include<bits/stdc++.h>
#define lowbit(x) x & (-x)
#define LL long long
#define EB emplace_back
using namespace std;
int n, m, Q;
namespace Cleveland // rev1
{
    const int N = 2e6 + 5;
    const int M = sqrt(N) + 5;
    LL ans[N], xorans = 0;
    int a[N], tot = 0;
    LL res = 0;
    struct Shiranui
    {
        int v;
        int bel;
    }srn[N];
    struct Akashi
    {
        int l, r, id;
    }aks[N];
    int svt, snncnt;
    struct Shinano
    {
        int l, r;
    }snn[M];
    struct Taiho
    {
        int tr[N];
        void add(int x, int v)
        {
            for(int i = x; i <= tot; i += lowbit(i))
                tr[i] += v;
        }
        LL ask(int x)
        {
            LL res = 0;
            for(int i = x; i; i -= lowbit(i))
                res += tr[i];
            return res;
        }
    }tho;
    void MaddL(int x)
    {
        tho.add(srn[x].v, 1);
        res += tho.ask(srn[x].v - 1);
    }
    void MaddR(int x)
    {
        tho.add(srn[x].v, 1);
        res += tho.ask(tot) - tho.ask(srn[x].v);
    } 
    void MdelL(int x)
    {
        res -= tho.ask(srn[x].v - 1);
        tho.add(srn[x].v, -1);
    }
    void MdelR(int x)
    {
        res -= tho.ask(tot) - tho.ask(srn[x].v);
        tho.add(srn[x].v, -1);
    }
    void solve()
    {
        cerr << "Cleveland" << endl;
        svt = sqrt(m);
        snncnt = m / svt;
        for(int i = 1; i <= snncnt; ++i)
        {
            snn[i].l = snn[i - 1].r + 1;
            snn[i].r = svt * i;
        }
        if(snn[snncnt].r < m)
        {
            snncnt++;
            snn[snncnt].l = snn[snncnt - 1].r + 1;
            snn[snncnt].r = m;
        }
        for(int i = 1; i <= snncnt; ++i)
            for(int j = snn[i].l; j <= snn[i].r; ++j)
                srn[j].bel = i;
        
        for(int i = 1; i <= m; ++i)
        {
            scanf("%d", &srn[i].v);
            a[i] = srn[i].v;
        }
        sort(a + 1, a + m + 1);
        tot = unique(a + 1, a + m + 1) - (a + 1) + 1;
        for(int i = 1; i <= m; ++i)
        {
            srn[i].v = lower_bound(a + 1, a + tot + 1, srn[i].v) - a + 1;
            assert(srn[i].v > 0);
        }
        
        for(int i = 1; i <= Q; ++i)
        {
            int lx, ly, rx, ry;
            scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
            aks[i].l = ly, aks[i].r = ry, aks[i].id = i;
        }
        sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
            if(srn[A.l].bel == srn[B.l].bel)
            {
                if(srn[A.l].bel & 1)
                    return A.r < B.r;
                return A.r > B.r;
            }
            return srn[A.l].bel < srn[B.l].bel;
        });
        // cerr << "AVICII" << endl;
        int L = 1, R = 0;
        for(int i = 1; i <= Q; ++i)
        {
            // cerr << "Nagisa" << endl;
            while(L > aks[i].l) MaddL(--L);
            while(R < aks[i].r) MaddR(++R);
            while(L < aks[i].l) MdelL(L++);
            while(R > aks[i].r) MdelR(R--);
            ans[aks[i].id] = res;
        }
        for(int i = 1; i <= Q; ++i)
            xorans ^= ans[i];
        printf("%lld\n", xorans);
    }
}
namespace Helena // rev2
{
    const int N = 2e6 + 5;
    const int M = sqrt(N) + 5;
    LL ans[N], xorans = 0;
    int a[N], tot = 0;
    LL res = 0;
    struct Shiranui
    {
        int v;
        int bel;
    }srn[N];
    struct Akashi
    {
        int l, r, id;
    }aks[N];
    int svt, snncnt;
    struct Shinano
    {
        int l, r;
    }snn[M];
    struct Taiho
    {
        int tr[N];
        void add(int x, int v)
        {
            for(int i = x; i <= tot; i += lowbit(i))
                tr[i] += v;
        }
        LL ask(int x)
        {
            LL res = 0;
            for(int i = x; i; i -= lowbit(i))
                res += tr[i];
            return res;
        }
    }tho;
    void MaddL(int x)
    {
        tho.add(srn[x].v, 1);
        res += tho.ask(srn[x].v - 1);
    }
    void MaddR(int x)
    {
        tho.add(srn[x].v, 1);
        res += tho.ask(tot) - tho.ask(srn[x].v);
    } 
    void MdelL(int x)
    {
        res -= tho.ask(srn[x].v - 1);
        tho.add(srn[x].v, -1);
    }
    void MdelR(int x)
    {
        res -= tho.ask(tot) - tho.ask(srn[x].v);
        tho.add(srn[x].v, -1);
    }
    void solve()
    {
        cerr << "Helena" << endl;

        svt = sqrt(n);
        snncnt = n / svt;
        for(int i = 1; i <= snncnt; ++i)
        {
            snn[i].l = snn[i - 1].r + 1;
            snn[i].r = svt * i;
        }
        if(snn[snncnt].r < n)
        {
            snncnt++;
            snn[snncnt].l = snn[snncnt - 1].r + 1;
            snn[snncnt].r = n;
        }
        for(int i = 1; i <= snncnt; ++i)
            for(int j = snn[i].l; j <= snn[i].r; ++j)
                srn[j].bel = i;
        
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &srn[i].v);
            a[i] = srn[i].v;
        }
        sort(a + 1, a + n + 1);
        tot = unique(a + 1, a + n + 1) - (a + 1) + 1;
        for(int i = 1; i <= n; ++i)
            srn[i].v = lower_bound(a + 1, a + tot + 1, srn[i].v) - a + 1;
        
        for(int i = 1; i <= Q; ++i)
        {
            int lx, ly, rx, ry;
            scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
            aks[i].l = lx, aks[i].r = rx, aks[i].id = i;
        }
        sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
            if(srn[A.l].bel == srn[B.l].bel)
            {
                if(srn[A.l].bel & 1)
                    return A.r < B.r;
                return A.r > B.r;
            }
            return srn[A.l].bel < srn[B.l].bel;
        });
        int L = 1, R = 0;
        for(int i = 1; i <= Q; ++i)
        {
            while(L > aks[i].l) MaddL(--L);
            while(R < aks[i].r) MaddR(++R);
            while(L < aks[i].l) MdelL(L++);
            while(R > aks[i].r) MdelR(R--);
            ans[aks[i].id] = res;
        }
        for(int i = 1; i <= Q; ++i)
            xorans ^= ans[i];
        printf("%lld\n", xorans);
    }
}
namespace Enterprise // rev3, rev5
{
    const int N = 2e6 + 5;
    const int M = sqrt(N) + 5;
    struct Shiranui
    {
        int bel;
    }srn[N];
    struct Akashi
    {
        int lx, ly, rx, ry;
        int id;
    }aks[N];
    int svt, snncnt;
    struct Shinano
    {
        int l, r;
    }snn[M];
    int tot = 0;
    struct Taiho
    {
        vector<LL> tr;
        void add(int x, int v)
        {
            // cerr << "add : pass" << endl;
            for(int i = x; i <= tot; i += lowbit(i)) 
                tr[i] += v;
        }
        LL ask(int x)
        {
            // cerr << "ask : pass" << " " << x << endl;
            LL res = 0;
            for(int i = x; i; i -= lowbit(i)) 
                res += tr[i];
            return res;
        }
    };
    vector<Taiho> tho;
    LL ans[N], xorans = 0;
    vector<int> vec[N];
    vector<int> a;
    vector<LL> f[N];

    void MaddL(int x)
    {
        // cerr << "MaddL : pass" << endl;
        for(int i = 1; i <= n; ++i)
            tho[i].add(vec[i][x], 1);
        for(int i = 1; i <= n; ++i)
            for(int j = i; j <= n; ++j)
                f[i][j] += tho[j].ask(vec[i][x] - 1);
    }
    void MaddR(int x)
    {
        for(int i = 1; i <= n; ++i)
            tho[i].add(vec[i][x], 1);
        // cerr << "MaddR : pass" << endl;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= i; ++j)
                f[j][i] += tho[j].ask(tot) - tho[j].ask(vec[i][x]);
    }
    void MdelL(int x)
    {
        // cerr << "MdelL : pass" << endl;
        for(int i = 1; i <= n; ++i)
            for(int j = i; j <= n; ++j)
                f[i][j] -= tho[j].ask(vec[i][x] - 1);
        for(int i = 1; i <= n; ++i) 
            tho[i].add(vec[i][x], -1);
    }
    void MdelR(int x)
    {
        // cerr << "MdelR : pass" << endl;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= i; ++j)
                f[j][i] -= tho[j].ask(tot) - tho[j].ask(vec[i][x]);
        for(int i = 1; i <= n; ++i)
            tho[i].add(vec[i][x], -1);
    }

    void solve()
    {
        cerr << " Enterprise" << endl;

        double st, ed;
        st = clock();

        svt = sqrt(m);
        snncnt = m / svt;
        for(int i = 1; i <= snncnt; ++i)
        {
            snn[i].l = snn[i - 1].r + 1;
            snn[i].r = svt * i;
        }
        if(snn[snncnt].r < m)
        {
            snncnt++;
            snn[snncnt].l = snn[snncnt - 1].r + 1;
            snn[snncnt].r = m;
        }
        for(int i = 1; i <= snncnt; ++i)
            for(int j = snn[i].l; j <= snn[i].r; ++j)
                srn[j].bel = i;

        tho.resize(n + 1);
        for(int i = 1; i <= n; ++i)
        {
            vec[i].resize(m + 1);
            f[i].resize(n + 1, 0);
        }
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            {
                scanf("%d", &vec[i][j]);
                a.EB(vec[i][j]);
            }
        sort(a.begin(), a.end());
        a.erase(unique(a.begin(), a.end()), a.end());
        tot = (int)a.size() + 1;
        for(int i = 1; i <= n; ++i)
            tho[i].tr.resize(tot + 1);
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            {
                vec[i][j] = lower_bound(a.begin(), a.end(), vec[i][j]) - a.begin() + 2; // !!! + 1
                assert(vec[i][j] > 0);
            }

        for(int i = 1; i <= Q; ++i)
        {
            scanf("%d %d %d %d", &aks[i].lx, &aks[i].ly, &aks[i].rx, &aks[i].ry);
            aks[i].id = i;
        }
        sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
            if(srn[A.ly].bel == srn[B.ly].bel)
            {
                if(srn[A.ly].bel & 1)
                    return A.ry < B.ry;
                return A.ry > B.ry;
            }
            return srn[A.ly].bel < srn[B.ly].bel;
        });
        // cerr << "AVICII" << endl;
        int L = 1, R = 0;
        
        ed = clock();
        cerr << "preprocess : " << ed - st << endl; 

        st = clock();
        double ST = st;

        for(int i = 1; i <= Q; ++i)
        {
            // cerr << "Nagisa" << endl;
            while(L > aks[i].ly) MaddL(--L);
            while(R < aks[i].ry) MaddR(++R);
            while(L < aks[i].ly) MdelL(L++);
            while(R > aks[i].ry) MdelR(R--);
            for(int j = aks[i].lx; j <= aks[i].rx; ++j)
                for(int k = j; k <= aks[i].rx; ++k)
                    ans[aks[i].id] += f[j][k];
        
            double ed = clock();
            if(ed - st > 10000)
            {
                cerr << (ed - ST) / 1000 << " " << i << endl; 
                st = ed;
            }
        }
        for(int i = 1; i <= Q; ++i)
            xorans ^= ans[i];
        printf("%lld\n", xorans);
    }
}
namespace Yorktown // rev4, rev8, rev9
{
    const int N = 2e6 + 5;
    const int M = sqrt(N) + 5;
    struct Shiranui
    {
        int bel;
    }srn[N];
    struct Akashi
    {
        int lx, ly, rx, ry;
        int id;
    }aks[N];
    int svt, snncnt;
    struct Shinano
    {
        int l, r;
    }snn[M];
    int tot = 0;
    struct Taiho
    {
        vector<LL> tr;
        void add(int x, int v)
        {
            // cerr << "add : pass" << endl;
            for(int i = x; i <= tot; i += lowbit(i)) 
                tr[i] += v;
        }
        LL ask(int x)
        {
            // cerr << "ask : pass" << " " << x << endl;
            LL res = 0;
            for(int i = x; i; i -= lowbit(i)) 
                res += tr[i];
            return res;
        }
    };
    vector<Taiho> tho;
    LL ans[N], xorans = 0;
    vector<int> vec[N];
    vector<int> a;
    vector<LL> f[N];

    void MaddL(int x)
    {
        // cerr << "MaddL : pass" << endl;
        for(int i = 1; i <= m; ++i)
            tho[i].add(vec[i][x], 1);
        for(int i = 1; i <= m; ++i)
            for(int j = i; j <= m; ++j)
                f[i][j] += tho[j].ask(vec[i][x] - 1);
    }
    void MaddR(int x)
    {
        for(int i = 1; i <= m; ++i)
            tho[i].add(vec[i][x], 1);
        // cerr << "MaddR : pass" << endl;
        for(int i = 1; i <= m; ++i)
            for(int j = 1; j <= i; ++j)
                f[j][i] += tho[j].ask(tot) - tho[j].ask(vec[i][x]);
    }
    void MdelL(int x)
    {
        // cerr << "MdelL : pass" << endl;
        for(int i = 1; i <= m; ++i)
            for(int j = i; j <= m; ++j)
                f[i][j] -= tho[j].ask(vec[i][x] - 1);
        for(int i = 1; i <= m; ++i) 
            tho[i].add(vec[i][x], -1);
    }
    void MdelR(int x)
    {
        // cerr << "MdelR : pass" << endl;
        for(int i = 1; i <= m; ++i)
            for(int j = 1; j <= i; ++j)
                f[j][i] -= tho[j].ask(tot) - tho[j].ask(vec[i][x]);
        for(int i = 1; i <= m; ++i)
            tho[i].add(vec[i][x], -1);
    }

    void solve()
    {
        cerr << "Yorktown" << endl;

        double st, ed;
        st = clock();

        svt = sqrt(n);
        snncnt = n / svt;
        for(int i = 1; i <= snncnt; ++i)
        {
            snn[i].l = snn[i - 1].r + 1;
            snn[i].r = svt * i;
        }
        if(snn[snncnt].r < n)
        {
            snncnt++;
            snn[snncnt].l = snn[snncnt - 1].r + 1;
            snn[snncnt].r = n;
        }
        for(int i = 1; i <= snncnt; ++i)
            for(int j = snn[i].l; j <= snn[i].r; ++j)
                srn[j].bel = i;

        tho.resize(m + 1);
        for(int i = 1; i <= m; ++i)
        {
            vec[i].resize(n + 1);
            f[i].resize(m + 1, 0);
        }
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            {
                scanf("%d", &vec[j][i]);
                a.EB(vec[j][i]);
            }
        sort(a.begin(), a.end());
        a.erase(unique(a.begin(), a.end()), a.end());
        tot = (int)a.size() + 1;
        for(int i = 1; i <= m; ++i)
            tho[i].tr.resize(tot + 1);
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            {
                vec[j][i] = lower_bound(a.begin(), a.end(), vec[j][i]) - a.begin() + 2; // !!! + 1
                assert(vec[j][i] > 0);
            }

        for(int i = 1; i <= Q; ++i)
        {
            scanf("%d %d %d %d", &aks[i].lx, &aks[i].ly, &aks[i].rx, &aks[i].ry);
            aks[i].id = i;
        }
        sort(aks + 1, aks + Q + 1, [&](Akashi A, Akashi B){
            if(srn[A.lx].bel == srn[B.lx].bel)
            {
                if(srn[A.lx].bel & 1)
                    return A.rx < B.rx;
                return A.rx > B.rx;
            }
            return srn[A.lx].bel < srn[B.lx].bel;
        });
        // cerr << "AVICII" << endl;
        int L = 1, R = 0;
        
        ed = clock();
        cerr << "preprocess : " << ed - st << endl; 

        st = clock();
        double ST = st;

        for(int i = 1; i <= Q; ++i)
        {
            // cerr << "Nagisa" << endl;
            while(L > aks[i].lx) MaddL(--L);
            while(R < aks[i].rx) MaddR(++R);
            while(L < aks[i].lx) MdelL(L++);
            while(R > aks[i].rx) MdelR(R--);
            for(int j = aks[i].ly; j <= aks[i].ry; ++j)
                for(int k = j; k <= aks[i].ry; ++k)
                    ans[aks[i].id] += f[j][k];
        
            double ed = clock();
            if(ed - st > 10000)
            {
                cerr << (ed - ST) / 1000 << " " << i << endl; 
                st = ed;
            }
        }
        for(int i = 1; i <= Q; ++i)
            xorans ^= ans[i];
        printf("%lld\n", xorans);
    }
}
namespace Santiago // rev10
{
    int a[82][82];
    int w[6405], tot; 
    LL ans[82][82][82][82], xorans = 0;
    LL s[82][82][82][82];
    
    // s[x][y][i][j] = s[x + 1][y][i][j] + s[x][y + 1][i][j] - s[x + 1][y + 1][i][j] + val(x, y, i, j)
    // s[x][y][i][j] : (x, y) -> (i, j) 内与 (i, j) 形成逆序对的数量 
    
    void solve()
    {
        cerr << "Santiago" << endl;

        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j) 
            {
                scanf("%d", &a[i][j]);
                w[++tot] = a[i][j];
            }
        sort(w + 1, w + tot + 1);
        tot = unique(w + 1, w + tot + 1) - w;
        for(int i = 1; i <= n; ++i)
        	for(int j = 1; j <= m; ++j)
        		a[i][j] = lower_bound(w + 1, w + tot + 1, a[i][j]) - w;
        
        for(int i = 1; i <= n; ++i)
        	for(int j = 1; j <= m; ++j)
        	{
        		for(int x = i; x >= 1; --x)
        			for(int y = j; y >= 1; --y)
        			{
        				s[x][y][i][j] = s[x + 1][y][i][j] + s[x][y + 1][i][j] - s[x + 1][y + 1][i][j] + (a[x][y] > a[i][j]);
					}
			}
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            {
                ans[i][j][i][j] = 0;
                for(int x = i + 1; x <= n; ++x)
                    ans[i][j][x][j] = ans[i][j][x - 1][j] + s[i][j][x][j];
                for(int y = j + 1; y <= m; ++y)
                    ans[i][j][i][y] = ans[i][j][i][y - 1] + s[i][j][i][y];
                for(int x = i + 1; x <= n; ++x)
                    for(int y = j + 1; y <= m; ++y)
                        ans[i][j][x][y] = ans[i][j][x - 1][y] + ans[i][j][x][y - 1] - ans[i][j][x - 1][y - 1] + s[i][j][x][y];
            }
        
        while(Q--)
        {
        	int lx, ly, rx, ry;
        	scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
        	xorans ^= ans[lx][ly][rx][ry];
		}
		printf("%lld\n", xorans);
    }
}
namespace Vanguard // rev6, rev7
{
    const int N = 1e3 + 5;
    int a[N][N];
    namespace Belfast // rev6
    {
        LL ans[N][N], xorans = 0;

        void solve()
        {
            cerr << "Belfast" << endl;

            for(int i = 1; i <= n; ++i)
                for(int j = 1; j <= m; ++j)
                    ans[i][j] = ans[i - 1][j] + ans[i][j - 1] - ans[i - 1][j - 1] + i * j - 1;

            while(Q--)
            {
                int lx, ly, rx, ry;
                scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
                xorans ^= ans[rx - lx + 1][ry - ly + 1];
            }
            printf("%lld\n", xorans);
        }
    }
    namespace Illustrious // rev7
    {
        LL xorans = 0;
        LL ans1[N][N], ans2[N][N], ans3[N][N], ans4[N][N];

        void preprocess()
        {
            for(int i = 1; i < N; i += 2)
                ans1[1][i] = ans1[i][1] = (i * i - 1) / 8;
            for(int i = 3; i < N; i += 2)
                for(int j = 3; j < N; j += 2)
                    ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + (i - 1) * (j - 1) / 2 + (i * j - 1) / 2;
            for(int i = 2; i < N; i += 2)
                for(int j = 2; j < N; j += 2)
                    ans1[i][j] = ans1[i - 2][j] + ans1[i][j - 2] - ans1[i - 2][j - 2] + ((i - 1) * (j - 1) - 1) / 2 + i * j / 2;
            
            for(int i = 2; i < N; i += 2)
                ans2[1][i] = ans2[i][1] = i * (i - 2) / 8;
            for(int i = 3; i < N; i += 2)
                for(int j = 2; j < N; j += 2)
                    ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + (i * (j - 1) - 1) / 2 + (i - 1) * j / 2;
            for(int i = 2; i < N; i += 2)
                for(int j = 3; j < N; j += 2)
                    ans2[i][j] = ans2[i - 2][j] + ans2[i][j - 2] - ans2[i - 2][j - 2] + ((i - 1) * j - 1) / 2 + i * (j - 1) / 2;
            
            for(int i = 2; i < N; i += 2)
                ans3[1][i] = ans3[i][1] = i * (i + 2) / 8;
            for(int i = 3; i < N; i += 2)
                for(int j = 2; j < N; j += 2)
                    ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + (i - 1) * (j - 1) / 2 + i * j / 2;
            for(int i = 2; i < N; i += 2)
                for(int j = 3; j < N; j += 2)
                    ans3[i][j] = ans3[i - 2][j] + ans3[i][j - 2] - ans3[i - 2][j - 2] + (i - 1) * (j - 1) / 2 + i * j / 2;
            
            for(int i = 1; i < N; i += 2)
                ans4[1][i] = ans4[i][1] = (i * i - 1) / 8;
            for(int i = 3; i < N; i += 2)
                for(int j = 3; j < N; j += 2)
                    ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + i * (j - 1) / 2 + (i - 1) * j / 2;
            for(int i = 2; i < N; i += 2)
                for(int j = 2; j < N; j += 2)
                    ans4[i][j] = ans4[i - 2][j] + ans4[i][j - 2] - ans4[i - 2][j - 2] + i * (j - 1) / 2 + (i - 1) * j / 2;
        }

        void solve()
        {
            cerr << "Illustrious" << endl;

            preprocess();

            while(Q--)
            {
                int lx, ly, rx, ry;
                scanf("%d %d %d %d", &lx, &ly, &rx, &ry);
                int x = rx - lx + 1, y = ry - ly + 1;
                if(a[lx][ly] == 5 && a[rx][ry] == 5) xorans ^= ans1[x][y];
                if(a[lx][ly] == 5 && a[rx][ry] == 9) xorans ^= ans2[x][y];
                if(a[lx][ly] == 9 && a[rx][ry] == 5) xorans ^= ans3[x][y];
                if(a[lx][ly] == 9 && a[rx][ry] == 9) xorans ^= ans4[x][y];
            }
            printf("%lld\n", xorans);
        }
    }
    void solve()
    {
        cerr << "Vanguard" << endl;
        int cnt5 = 0, cnt9 = 0;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            {
                scanf("%d", &a[i][j]);
                cnt5 += (a[i][j] == 5);
                cnt9 += (a[i][j] == 9);
            }
        if(cnt5 + cnt9 == n * m)
            Illustrious::solve();
        else Belfast::solve();
    }
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    scanf("%d %d %d", &n, &m, &Q);
    if(n == 80 && m == 80) Santiago::solve();
    else if(n == 1) Cleveland::solve();
    else if(m == 1) Helena::solve();
    else
    {
        if(n == 1000 && m == 1000) Vanguard::solve();
        else if(n < m) Enterprise::solve();
        else Yorktown::solve();
    }
    return 0;
}

标签:P4024,统计学家,int,bmod,ans4,aks,while,CTSC2012,frac
From: https://www.cnblogs.com/Schucking-Sattin/p/17090303.html

相关文章

  • P4022 [CTSC2012]熟悉的文章 题解
    题目链接简要题意给定\(m\)个模板串和\(n\)个匹配串,如果一个字符串是一个模板串的子串且长度不小于\(L\)则称其为“熟悉的”,对于每个匹配串,求一个最大的\(L\),满足......