申明:由于本人卡常技艺不佳,本题解复杂度正确但无法通过

首先分块,然后考虑分开计算贡献维护,看下面一张图:

我们将贡献拆分为 \(ans(A) + ans(B) + ans(C) + ans(AB) + ans(AC) + ans(BC)\),然后考虑逐一维护。

首先散块内部先离散化,然后用树状数组记录散块前后缀逆序对数量,然后散块对整块的贡献考虑枚举散块中的数,然后对于每个块的结尾记录一个前缀和查询时差分求出贡献,散块对散块的贡献考虑将两个块先通过离散化后的数桶排一遍,然后归并排序计算贡献,整块之间的贡献直接预处理时递推处理。总复杂度 \(O(n \sqrt n + n \log n)\)。

然后就是常数巨大的代码,代码中写了注释可以辅助理解:

#include<bits/stdc++.h>
#define lowbit(x)(x&(-x))
#define ll long long
namespace IO{
const int SIZE=1<<21;
static char ibuf[SIZE],obuf[SIZE],*iS,*iT,*oS=obuf,*oT=oS+SIZE-1;
int qr;
char qu[55],c;
bool f;
#define getchar() (IO::iS==IO::iT?(IO::iT=(IO::iS=IO::ibuf)+fread(IO::ibuf,1,IO::SIZE,stdin),(IO::iS==IO::iT?EOF:*IO::iS++)):*IO::iS++)
#define putchar(x) *IO::oS++=x,IO::oS==IO::oT?flush():0
#define flush() fwrite(IO::obuf,1,IO::oS-IO::obuf,stdout),IO::oS=IO::obuf
#define puts(x) IO::Puts(x)
template<typename T>
inline void read(T&x){
for(f=1,c=getchar();c<48||c>57;c=getchar())f^=c=='-';
for(x=0;c<=57&&c>=48;c=getchar()) x=(x<<1)+(x<<3)+(c&15);
x=f?x:-x;
}
template<typename T>
inline void write(T x){
if(!x) putchar(48); if(x<0) putchar('-'),x=-x;
while(x) qu[++qr]=x%10^48,x/=10;
while(qr) putchar(qu[qr--]);
}
inline void Puts(const char*s){
for(int i=0;s[i];i++)
putchar(s[i]);
putchar('\n');
}
struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}
using IO::read;
using IO::write;
using namespace std;
const int maxn = 1e5+14;
const int maxsq = 320;
int n,m;
inline ll w(vector<int> &A,vector<int> &B){
int l1=0,l2=0;
ll res=0;
vector<int> r;
while(l1<A.size()||l2<B.size()){
if(l1==A.size()){
res+=(A.size()-l1);
r.push_back(B[l2]);
++l2;
}
else if(l2==B.size()){
r.push_back(A[l1]);
++l1;
}
else if(A[l1]<B[l2]){
r.push_back(A[l1]);
++l1;
}
else{
res+=(A.size()-l1);
r.push_back(B[l2]);
++l2;
}
}
A=r;
return res;
}
int sq;//块长
int cnt[maxn][maxsq];//前 i 个块中小于等于 j 的数的数量
int a[maxn];//序列
int pre[maxn],suf[maxn];//块内逆序对数量前缀后缀
int L[maxn],R[maxn],F[maxn];//每个块的起点终点 每个数所属的块
int rk[maxn];//每个数在块中的排名
ll G[maxsq][maxsq];//块 [l,r] 中的逆序对数量
int block_cnt[maxsq];
int tr[maxsq];
inline void add(int x){
while(x<=sq) tr[x]++,x+=lowbit(x);
}
inline int ask(int x){
int res=0;
while(x>0) res+=tr[x],x-=lowbit(x);
return res;
}
inline void rksort(vector<int> &A){//排序
for(int x:A){
block_cnt[rk[x]]=x;
}
A.clear();
for(int i=1;i<=sq;i=-~i){
if(block_cnt[i]!=0){
A.push_back(block_cnt[i]);
block_cnt[i]=0;
}
}
return ;
}
inline void block_init(int pos){
for(int i=L[pos];i<=R[pos];i=-~i){
G[pos][pos]+=(i-L[pos])-ask(rk[a[i]]);
add(rk[a[i]]);
pre[i]=G[pos][pos];
}
for(int i=1;i<=sq;++i) tr[i]=0; for(int i=R[pos];i>=L[pos];--i){
suf[i]=suf[i+1]+ask(rk[a[i]]);
add(rk[a[i]]);
}
for(int i=1;i<=sq;++i) tr[i]=0;
}
inline void init(){
sq = sqrt(n);
for(int i=1;i<=n;i=-~i){
if((i - 1)%sq == 0) F[i]=F[i-1]+1,L[F[i]]=i,R[F[i-1]]=i-1;
else F[i]=F[i-1];
}
R[F[n]]=n;
//编号处理
for(int i=1;i<=n;i=-~i){
for(int j=F[i];j<=F[n];++j){
++cnt[a[i]][j];
}
}
for(int j=1;j<=F[n];++j){
for(int i=1;i<=n;i=-~i) cnt[i][j]+=cnt[i-1][j];
}
//桶处理
for(int i=1;i<=F[n];i=-~i){
vector<int> p;
for(int j=L[i];j<=R[i];++j) p.push_back(a[j]);
sort(p.begin(),p.end());
for(int j=0;j<p.size();++j){
rk[p[j]]=j+1;
}
}
//排序
for(int i=1;i<=F[n];i=-~i) block_init(i);
for(int i=1;i<=F[n];i=-~i){
for(int j=i+1;j<=F[n];++j){
G[i][j]=G[i][j-1]+G[j][j];
for(int k=L[j];k<=R[j];++k){
G[i][j]+=(R[j-1]-L[i]+1)-(cnt[a[k]][j-1]-cnt[a[k]][i-1]);
}
}
}
}
inline ll query(ll l,ll r){
l=min(l,n*1ll),r=min(r,n*1ll);
if(l>r){
return 0;
}
if(F[l]==F[r]){
int res=0;
if(l!=L[F[r]]){
res+=(pre[r]-pre[l-1]);
vector<int> A,B;
for(int i=L[F[r]];i<l;i=-~i) A.push_back(a[i]);
for(int i=l;i<=r;i=-~i) B.push_back(a[i]);
rksort(A);
rksort(B);
res-=w(A,B);
}
else{
res=pre[r];
}
return res;
}
int bl=F[l]+1,br=F[r]-1;
if(F[r]==F[l]+1){
ll res=0;
res+=(suf[l]+pre[r]);
vector<int> A,B;
for(int i=l;i<=R[F[l]];i=-~i) A.push_back(a[i]);
for(int i=L[F[r]];i<=r;i=-~i) B.push_back(a[i]);
rksort(A);
rksort(B);
res+=w(A,B);
return res;
}
ll res=0;
//整块 散块 块内贡献
res+=(suf[l]+pre[r]+G[bl][br]);
//散块对散块的贡献
vector<int> A,B;
for(int i=l;i<=R[F[l]];i=-~i) A.push_back(a[i]);
for(int i=L[F[r]];i<=r;i=-~i) B.push_back(a[i]);
rksort(A);
rksort(B);
res+=w(A,B);
//散块对整块
for(int i=l;i<=R[F[l]];i=-~i){
res+=cnt[a[i]][br]-cnt[a[i]][bl-1];
}
//整块对散块
for(int i=L[F[r]];i<=r;i=-~i){
res+=(R[br]-L[bl]+1)-(cnt[a[i]][br]-cnt[a[i]][bl-1]);
}
return res;
}
ll lstans;
signed main(){
read(n);
read(m);
for(int i=1;i<=n;i=-~i){
read(a[i]);
}
init();
while(m--){
ll l,r;
read(l);
read(r);
write(lstans=query(l^lstans,r^lstans));
putchar('\n');
}
}

Yuno loves sqrt technology I 题解的更多相关文章

  1. 有关二次离线和 Yuno loves sqrt technology II

    二次离线 前置技能 莫队 修改查询 \(O(\sqrt n )-O(1)\) 平衡 概念 考虑朴素莫队离线询问,过程中维护信息从 \([l,r]\) 扩展为 \([l\pm 1,r\pm 1]\) , ...

  2. 题解 Yuno loves sqrt technology II

    题目传送门 题目大意 有\(n\)个数,\(m\)个查询,每次查询一个区间内的逆序对个数. \(n,m\le 10^5\) 思路 其实是为了锻炼二次离线才做这道题的. 不难想到可以有一个\(\Thet ...

  3. [洛谷P5048][Ynoi2019模拟赛]Yuno loves sqrt technology III

    题目大意:有$n(n\leqslant5\times10^5)$个数,$m(m\leqslant5\times10^5)$个询问,每个询问问区间$[l,r]$中众数的出现次数 题解:分块,设块大小为$ ...

  4. [Ynoi2019模拟赛]Yuno loves sqrt technology II

    题目大意: 给定一个长为\(n\)的序列,\(m\)次询问,每次查询一个区间的逆序对数. 32MB. 解题思路: 出题人题解 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 二次离线莫队. 对于每个区 ...

  5. [Ynoi2019模拟赛]Yuno loves sqrt technology I

    题目描述 给你一个长为n的排列,m次询问,每次查询一个区间的逆序对数,强制在线. 题解 MD不卡了..TMD一点都卡不动. 强制在线的话也没啥好一点的方法,只能分块预处理了. 对于每个块,我们设lef ...

  6. [Ynoi2019模拟赛]Yuno loves sqrt technology III

    题目大意: 给你一个长为n的序列a,m次询问,每次查询一个区间的众数的出现次数,强制在线. 解题思路: 出题人题解 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 首先得离散化. 分块后,预处理Fi, ...

  7. [Ynoi2019模拟赛]Yuno loves sqrt technology II(二次离线莫队)

    二次离线莫队. 终于懂了 \(lxl\) 大爷发明的二次离线莫队,\(\%\%\%lxl\) 二次离线莫队,顾名思义就是将莫队离线两次.那怎么离线两次呢? 每当我们将 \([l,r]\) 移动右端点到 ...

  8. [Luogu5048] [Ynoi2019模拟赛]Yuno loves sqrt technology III[分块]

    题意 长为 \(n\) 的序列,询问区间众数,强制在线. \(n\leq 5\times 10^5\). 分析 考虑分块,暴力统计出整块到整块之间的众数次数. 然后答案还可能出现在两边的两个独立的块中 ...

  9. [luogu5048] [Ynoi2019模拟赛] Yuno loves sqrt technology III

    题目链接 洛谷. Solution 思路同[BZOJ2724] [Violet 6]蒲公英,只不过由于lxl过于毒瘤,我们有一些更巧妙的操作. 首先还是预处理\(f[l][r]\)表示\(l\sim ...

  10. 洛谷P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III(分块)

    传送门 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 用蒲公英那个分块的方法做结果两天没卡过去→_→ 首先我们分块,预处理块与块之间的答案,然后每次询问的时候拆成整块和两边剩下的元素 整块的答案很简 ...

随机推荐

  1. 模型压缩与部署-书生浦语大模型实战营学习笔记5&大语言模型11

    大语言模型-11.模型压缩与部署 书生浦语大模型实战营学习笔记4-模型压缩与部署 本文包括第二期实战营的第5课内容,介绍关于模型压缩的相关内容,主要包括.模型量化和模型部署的相关内容. 模型部署 定义 ...

  2. ruby操作excel

    操作xlsx axlsx插件 操作xls spreadsheet插件

  3. Windows有自带的远程桌面 为啥还要商业远程桌面

    网上有一类观点:最好的远程桌面就是windows自带的远程桌面. 那我们打破砂锅问到底,亲手实践下看看. 首先,我们来到了windows官网-远程桌面介绍页面. 如何使用远程桌面 设置你想要连接以使其 ...

  4. Unity新的MeshData API学习

    在新版本的Unity中提供了MeshDataArray和MeshData等多个API,使Mesh数据操作支持多线程:以更好的支持DOTS. API文档:https://docs.unity3d.com ...

  5. C 语言编程 — 基本语法

    目录 文章目录 目录 前文列表 C 语言 C 语言的版本 C 语言的特点 C 语言的优点 C 语言的缺点 搭建编程环境 基本语法 前文列表 <程序编译流程与 GCC 编译器> C 语言 C ...

  6. 继承与ER图

    会员是用户吗? 实体与集合 er图叫实体联系图.什么是实体?是现实中存在的事物个体,用户背后是实际存在的单个人. 对象->实体 类->实体的集合 er图描述的是实体间的联系 会员是真实存在 ...

  7. PyQGIS二次开发指南

    当你的数据处理使用的是Python语言,而你的导师又让你开发界面,那么PyQGIS二次开发指南是你必读的圣经.QGIS支持Python语言进行二次开发,你将学会如何使用Qt Designer进行界面设 ...

  8. 如何解决 IntelliJ Idea 编译 Java 项目时,找不到包或找不到符号的问题?

    执行 Maven Reimport 描述: 重新导入 Maven 包. 操作步骤: -> 选择 Project 目录右键 -> Maven -> Reimport 执行 Invali ...

  9. Android 13 - Media框架(14)- OpenMax(二)

    关注公众号免费阅读全文,进入音视频开发技术分享群! 这一节我们将来解析 media.codec 这个 HIDL service 究竟提供了什么服务,服务是如何启动的. 1.main 函数 我们先来看 ...

  10. OC的引用计数

    一.引用计数 引用计数是Objetive-C语言的内存管理机制,用于管理OC对象(通常指包含isa指针的结构体)的内存. 一个对象的引用计数为大于0的计数,表示这个对象被持有,不能被释放,当引用计数为 ...