BZOJ3787:Gty的文艺妹子序列(分块,树状数组)
Description
Input
Output
对每个询问,单独输出一行,表示al...ar中的逆序对数。对每个询问,单独输出一行,表示al...ar中的逆序对数。
Sample Input
1 7 5 6 9 4 9 4 4 7
10
0 4 6
0 5 8
0 1 10
1 25 19
0 19 25
1 14 4
0 12 12
0 2 5
1 8 7
1 1 10
Sample Output
2
3
16
13
0
2
Solution
分块,同时维护几个数组:
$f[i]$表示第$i$块内部的逆序对个数。
$g[i][j]$表示第$i$块和第$j$块能形成的逆序对个数,第二维用树状数组维护。
$s[i][j]$表示前$i$块里$j$数出现的次数,第二维同样用树状数组维护。
查询就利用这三个数组查一下,利用好树状数组前缀和的性质。乱七八糟加加减减。
修改就维护好这三个数组就好了……
速度倒数第二$46s$低空飞过……心情简单……
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N (50009)
#define S (259)
using namespace std; int n,m,opt,l,r,ans,num,f[S],a[N];
int ID[N],L[S],R[S]; inline int read()
{
int x=,w=; char c=getchar();
while (c<'' || c>'') {if (c=='-') w=-; c=getchar();}
while (c>='' && c<='') x=x*+c-'', c=getchar();
return x*w;
} struct BIT
{
int c[N];
void Update(int x,int v)
{
for (; x<=n; c[x]+=v,x+=(x&-x));
}
int Query(int x)
{
int ans=;
for (; x; ans+=c[x],x-=(x&-x));
return ans;
}
}B,g[S],s[S]; void Build()
{
int unit=sqrt(n);
num=n/unit+(n%unit!=);
for (int i=; i<=num; ++i)
L[i]=(i-)*unit+, R[i]=i*unit;
R[num]=n;
for (int i=; i<=num; ++i)
for (int j=L[i]; j<=R[i]; ++j) ID[j]=i;
} void Preprocess()
{
for (int i=; i<=num; ++i)
{
for (int j=L[i]; j<=R[i]; ++j)
{
f[i]+=B.Query(n)-B.Query(a[j]);
B.Update(a[j],);
}
for (int j=L[i]; j<=R[i]; ++j) B.Update(a[j],-);
}
for (int i=; i<=num; ++i)
for (int j=; j<=i-; ++j)
{
for (int k=L[j]; k<=R[j]; ++k) B.Update(a[k],);
for (int k=L[i]; k<=R[i]; ++k) g[i].Update(j,B.Query(n)-B.Query(a[k]));
for (int k=L[j]; k<=R[j]; ++k) B.Update(a[k],-);
}
for (int i=; i<=num; ++i)
for (int j=L[i]; j<=R[i]; ++j) s[i].Update(a[j],);
for (int i=; i<=num; ++i)
for (int j=; j<=n; ++j) s[i].Update(j,s[i-].Query(j)-s[i-].Query(j-));
} int Calc(int l,int r)
{
int ans=;
if (ID[l]==ID[r])
{
for (int i=l; i<=r; ++i)
{
ans+=B.Query(n)-B.Query(a[i]);
B.Update(a[i],);
}
for (int i=l; i<=r; ++i) B.Update(a[i],-);
return ans;
}
for (int i=l; i<=R[ID[l]]; ++i)
{
ans+=s[ID[r]-].Query(a[i]-)-s[ID[l]].Query(a[i]-);
ans+=B.Query(n)-B.Query(a[i]);
B.Update(a[i],);
}
for (int i=l; i<=R[ID[l]]; ++i) B.Update(a[i],-); for (int i=L[ID[r]]; i<=r; ++i)
{
ans+=(s[ID[r]-].Query(n)-s[ID[r]-].Query(a[i]))-(s[ID[l]].Query(n)-s[ID[l]].Query(a[i]));
ans+=B.Query(n)-B.Query(a[i]);
B.Update(a[i],);
}
for (int i=L[ID[r]]; i<=r; ++i) B.Update(a[i],-); for (int i=ID[l]+; i<=ID[r]-; ++i) ans+=f[i];
for (int i=ID[l]+; i<=ID[r]-; ++i)
ans+=g[i].Query(i-)-g[i].Query(ID[l]);
for (int i=l; i<=R[ID[l]]; ++i) B.Update(a[i],);
for (int i=L[ID[r]]; i<=r; ++i) ans+=B.Query(n)-B.Query(a[i]);
for (int i=l; i<=R[ID[l]]; ++i) B.Update(a[i],-);
return ans;
} void Change(int x,int k)
{
int id=ID[x];
for (int i=id; i<=num; ++i) s[i].Update(a[x],-);
for (int i=id; i<=num; ++i) s[i].Update(k,); for (int i=; i<=id-; ++i)
{
g[id].Update(i,-s[i].Query(n)+s[i].Query(a[x])+s[i-].Query(n)-s[i-].Query(a[x]));
g[id].Update(i,s[i].Query(n)-s[i].Query(k)-s[i-].Query(n)+s[i-].Query(k));
}
for (int i=id+; i<=num; ++i)
{
g[i].Update(id,-s[i].Query(a[x]-)+s[i-].Query(a[x]-));
g[i].Update(id,s[i].Query(k-)-s[i-].Query(k-));
} f[id]=; a[x]=k;
for (int i=L[id]; i<=R[id]; ++i)
{
f[id]+=B.Query(n)-B.Query(a[i]);
B.Update(a[i],);
}
for (int i=L[id]; i<=R[id]; ++i) B.Update(a[i],-);
} int main()
{
n=read();
Build();
for (int i=; i<=n; ++i) a[i]=read();
Preprocess();
m=read();
while (m--)
{
opt=read(); l=read(); r=read();
l^=ans; r^=ans;
if (opt==) printf("%d\n",ans=Calc(l,r));
else Change(l,r);
}
}
BZOJ3787:Gty的文艺妹子序列(分块,树状数组)的更多相关文章
- BZOJ3787 gty的文艺妹子序列 【树状数组】【分块】
题目分析: 首先这种乱七八糟的题目就分块.然后考虑逆序对的统计. 一是块内的,二是块之间的,三是一个块内一个块外,四是都在块外. 令分块大小为$S$. 块内的容易维护,单次维护时间是$O(S)$. 块 ...
- BZOJ 3787: Gty的文艺妹子序列 [分块 树状数组!]
传送门 题意:单点修改,询问区间内逆序对数,强制在线 看到加了!就说明花了不少时间.... 如果和上题一样预处理信息,用$f[i][j]$表示块i到j的逆序对数 强行修改的话,每个修改最多会修改$(\ ...
- BZOJ 3787 Gty的文艺妹子序列(分块+树状数组+前缀和)
题意 给出n个数,要求支持单点修改和区间逆序对,强制在线. n,m<=50000 题解 和不带修改差不多,预处理出smaller[i][j]代表前i块小于j的数的数量,但不能用f[i][j]代表 ...
- 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树
题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...
- 【BZOJ3744】Gty的妹子序列 分块+树状数组
[BZOJ3744]Gty的妹子序列 Description 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzo ...
- BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)
题面传送门 题目大意:给你一个序列,多次询问,每次取出一段连续的子序列$[l,r]$,询问这段子序列的逆序对个数,强制在线 很熟悉的分块套路啊,和很多可持久化01Trie的题目类似,用分块预处理出贡献 ...
- BZOJ 3744 Gty的妹子序列 分块+树状数组
具体分析见 搬来大佬博客 时间复杂度 O(nnlogn)O(n\sqrt nlogn)O(nnlogn) CODE #include <cmath> #include <cctyp ...
- BZOJ3787 : Gty的文艺妹子序列
将序列分成$\sqrt{n}$块,预处理出每两块之间的逆序对数,以及ap[i]表示前i块内数字出现次数的树状数组 预处理:$O(n\sqrt{n}\log n)$ 修改时,ap[i]可以在$O(\sq ...
- 【分块】【树状数组】bzoj3787 Gty的文艺妹子序列
题解懒得自己写了,Orz一发wangxz神犇的: http://bakser.gitcafe.com/2014/12/04/bzoj3787-Gty%E7%9A%84%E6%96%87%E8%89%B ...
随机推荐
- #if _MSC_VER > 1000 #pragma once #endif 含义
前提:MFC应用程序中,MainFrm 类头文件 MainFrm.h 中#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000解释 ...
- Java基础——Servlet(二)
好久没有写博客了,最近有在学习.可能是遇到瓶颈了,学到Servlet这里觉得有些吃力.前几天已经学完一遍了,但是学完之后觉得还是很迷茫.去知乎和百度上搜索,遇到的都是一些概念之类的讲解.核心的介绍说, ...
- 0 or 1(hdu2608)数学题
0 or 1 Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- Points on Cycle (hdu1700,几何)
Points on Cycle Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 解决:oracle+myBatis ResultMap 类型为 map 时,表字段类型有 Long/Blob/Clob 时报错
前言:最近在做一个通用查询单表的组件,所以 sql 的写法就是 select *,然后 resultType="map" .如果数据库中的表里有字段类型为 Long 等类型时,my ...
- php命令行生成项目结构
ghostinit.php <?php class ghostinit{ static $v = 'ghost version is 1.1'; static function init(){ ...
- POJ3468(KB7-C 线段树)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 108903 ...
- python3.8 新特性
https://docs.python.org/3.8/whatsnew/3.8.html python 3.8的新功能本文解释了与3.7相比,python 3.8中的新特性. 有关完整的详细信息,请 ...
- node.js(express)连接mongoDB入门指导
一.写在前面 人人都想成为全栈码农,作为一个web前端开发人员,通往全栈的简洁之路,貌似就是node.js了.前段时间学习了node.js,来谈谈新手如何快速的搭建自己的web服务,开启全栈之路. 二 ...
- BZOJ2957: 楼房重建(分块)
题意 题目链接 Sol 自己YY出了一个\(n \sqrt{n} \log n\)的辣鸡做法没想到还能过.. 可以直接对序列分块,我们记第\(i\)个位置的值为\(a[i] = \frac{H_i}{ ...