BZOJ 3744: Gty的妹子序列 [分块]

传送门

题意:询问区间内逆序对数



感觉这种题都成套路题了

两个预处理$f[i][j]$块i到j的逆序对数,$s[i][j]$前i块$\le j$的有多少个

f我直接处理成到元素j,方便一点

用个树状数组就行了

预处理和查询都带$log$所以还是开根号n比较科学吧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e4+5, M=300;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}

int n, a[N], Q, mp[N], l, r;
struct meow{int l,r;} b[M];
int block, m, pos[N];
inline void ini(){
    block=sqrt(n); m=(n-1)/block+1;
    for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
    for(int i=1;i<=m;i++) b[i].l=(i-1)*block+1, b[i].r=i*block;
    b[m].r=n;
}
struct Block{
    int c[N];
    inline void add(int p,int v) {for(;p<=*mp;p+=(p&-p)) c[p]+=v;}
    inline int sum(int p) {int re=0; for(;p;p-=(p&-p)) re+=c[p]; return re;}
    int f[M][N], s[M][N];
    void Set(int x){
        for(int i=b[x].l; i<=n; i++)
            f[x][i]= f[x][i-1]+sum(*mp)-sum(a[i]), add(a[i], 1);// printf("f %d %d  %d\n",x,i,f[x][i]);
        memset(c, 0, sizeof(c));

        for(int i=b[x].l; i<=b[x].r; i++) s[x][a[i]]++;
        for(int i=1; i<=*mp; i++) s[x][i]+= s[x][i-1];
        for(int i=1; i<=*mp; i++) s[x][i]+= s[x-1][i];// printf("s %d %d  %d\n",x,i,s[x][i]);;
    }

    int Que(int l,int r){
        int pl=pos[l], pr=pos[r];
        int ans=0;
        if(pl==pr){
            for(int i=l;i<=r;i++) ans+= sum(*mp)-sum(a[i]), add(a[i], 1);
            for(int i=l;i<=r;i++) add(a[i], -1);
        }else{
            ans= f[pl+1][r]; //printf("ans %d \n",ans);
            for(int i=b[pr].l; i<=r; i++) add(a[i], 1);
            for(int i=b[pl].r; i>=l; i--) ans+= sum(a[i]-1) + s[pr-1][a[i]-1] - s[pl][a[i]-1], add(a[i], 1);
            for(int i=b[pr].l; i<=r; i++) add(a[i], -1);
            for(int i=l; i<=b[pl].r; i++) add(a[i], -1);
        }
        return ans;
    }
}B;
int main(){
    freopen("in","r",stdin);
    n=read();
    for(int i=1;i<=n;i++) a[i]=mp[i]=read();
    sort(mp+1, mp+1+n); *mp=unique(mp+1, mp+1+n) - mp - 1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1, mp+1+*mp, a[i]) - mp;
    //for(int i=1;i<=n;i++) printf("%d ",a[i]); puts("");
    ini();
    for(int i=1;i<=m;i++) B.Set(i);

    Q=read(); int lastans=0;
    while(Q--){
        //l=read(), r=read();
        l=read()^lastans, r=read()^lastans;
        if(l>r) swap(l, r);
        lastans=B.Que(l, r); printf("%d\n",lastans);
    }
}
时间: 2024-10-09 13:24:57

BZOJ 3744: Gty的妹子序列 [分块]的相关文章

BZOJ 3744 Gty的妹子序列 分块+fenwick

题目大意:强制在线区间无修改逆序对. 思路:看到数据范围发现分块是很显然的.预处理了很多东西,比如说每个块里面的逆序对个数,还有f[i][j]表示从第i块到第j块的逆序对个数.如果仅仅处理到这里的话,后面是不太好处理的.我们还需要一个东西,是每个点对每个块的逆序对个数,并取前缀合优化.否则的话就得用主席树来乱搞,那常数 反正总时间复杂度大概是O(n*sqrt(n)*logn)  强行不到O(n^2) 剩下就是小事了, 比如离散话啥的.. CODE: #include <cmath> #incl

bzoj 3744: Gty的妹子序列 主席树+分块

3744: Gty的妹子序列 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 101  Solved: 34[Submit][Status] Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹子序列,于是Bakse

BZOJ 3744: Gty的妹子序列

3744: Gty的妹子序列 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1335  Solved: 379[Submit][Status][Discuss] Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹

bzoj 3744 Gty的妹子序列 区间逆序对数(在线) 分块

题目链接 题意 给定\(n\)个数,\(q\)个询问,每次询问\([l,r]\)区间内的逆序对数. 强制在线. 思路 参考:http://www.cnblogs.com/candy99/p/6579556.html 离线的话就如上一题bzoj 3289 Mato的文件管理,可以直接用 莫队 搞,在线的话怎么办呢? 分块大法好. 1 预处理出两个信息: \(f[i][j]\):从 第\(i\)块开始位置 到 位置\(j\) 这段区间的逆序对数 \(s[i][j]\):前\(i\)块中\(\leq

【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成了一个序列,每个妹子有一个美丽度. Bakser神犇与他打算研究一下这个妹子序列,于是Bakser神犇问道:"你知道区间 [l,r]中妹子们美丽度的逆序对数吗?" 蒟蒻Autumn只会离线乱搞啊……但是Bakser神犇说道:"强制在线." 请你帮助一下Autumn吧.

【BZOJ-3809】Gty的二逼妹子序列 分块 + 莫队算法

3809: Gty的二逼妹子序列 Time Limit: 80 Sec  Memory Limit: 28 MBSubmit: 1072  Solved: 292[Submit][Status][Discuss] Description Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题. 对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数. 为了方便,我们规定妹子们的美丽度全都在[1,n]中. 给定一个长度为n(1<=n<=100000)

BZOJ 3787 Gty的文艺妹子序列 分块+树状数组

题目大意:带修改.强制在线的区间逆序对 将之前3744TLE了的某个做法重写了一发 把其中一些预处理改成了树状数组 不得不说树状数组常数还是小啊 令g[i][j](i<=j)表示第i块中的元素与第i~j块中的元素之间的逆序对数 第一维暴力第二维树状数组维护前缀和 equals[i][j]表示前i块之内j的数量 这个直接暴力即可 smaller[i][j]表示前i块之内小于等于j的数的数量 第一维暴力第二维树状数组 修改时都维护一遍 查询时 首先我们把区间分为三块 令A为左侧零碎部分 B为中间成块

BZOJ 3720 Gty的妹子树 树上分块

题目大意:给出一棵树,要求维护:1.求出以x为根节点的子树的严格大于y的数量. 2.将一个节点的权值改变. 3.在一个节点下加一个权值为y的节点. 思路:分块这个东西太神了(别找我分析时间复杂度..树上的分块更神... 首先,分块的原则和正常分块一样,把一棵树分成√n块,每一块不超过√n个,然后所有的时间复杂度降到了O(√n),(这个题还有个排序,所以还有一个log(n)). 如何在树上分块.规定根节点在编号为1的块中,然后做一次深搜,如果遍历到的一个节点的时候当前节点所在的块的数量已经达到最大

BZOJ 3720: Gty的妹子树 [树上size分块]

传送门 题意: 一棵树,询问子树中权值大于$k$的节点个数,修改点权值,插入新点:强制在线 一开始以为询问多少种不同的权值,那道CF的强制在线带修改版,直接吓哭 然后发现看错了这不一道树上分块水题... 用王室联邦分块的话需要维护每一个块$dfs$序最小值和最大值,并且插入操作会破坏原来的性质 不如直接按$size$分块,根节点$size<block$就加入根,否则新建块 $size$分块不能保证块的数量,可以被菊花图卡掉,然而本题没有所以就可以安心的写了 每个块维护排序后的值 查询操作,不完整