题目描述

给你一个长为n的排列,m次询问,每次查询一个区间的逆序对数,强制在线。

题解

MD不卡了。。TMD一点都卡不动。

强制在线的话也没啥好一点的方法,只能分块预处理了。

对于每个块,我们设lef[i]表示i到这个i这个元素所在块的块头的区间逆序对,rig[i]表示到块尾的逆序对。

在设一个cnt[i][j]表示从第i个块到第j个块的逆序对。

然后考虑如何处理询问。

整块之间的可以直接O(1)取答案,对于散块,我们需要求出散块内部的答案,散块对整块的答案,散块对散块的答案。

对于散块内的,因为散块在当前块中一定是它的前缀或后缀,所以我们直接O(1)取答案。

对于散块对整块的,我们可以在维护一个tag[i][j]表示前i个块,大于/小于j的元素有多少个,然后询问就扫描散块,前缀和统计即可。

对于散块对散块的,可以在每个块内维护元素的相对大小,然后对于两个不相交的区间,可以用桶排+扫描求出逆序对。

但还有一个特殊情况,就是lr在同一个块里,前面的方法不是很实用。

我们设当前块头尾h,那么答案可以表示为ans(h-r)-ans(h-l)-ans(h~l,l~r),前两个部分已经求过了,后面的用桶排+扫描即可。

不过常数略大,开2s应该能过。

代码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize ("Ofast")
#pragma GCC optimize ("Ofast","inline","unroll-loops")
#pragma GCC optimize ("no-stack-protector")
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cassert>
#include <cmath>
#define N 100002
#define M 340
using namespace std;
typedef long long ll;
int n,m,tr[N],mis[M],rnk[N],n1,ji[M],be[N],a[N],b[M],lef[N],tag1[M][N],tag2[M][N],rig[N],tong[N];
int q[N],pos[N];
ll ans,cnt[M][M];
inline void add(int x,int y){while(x<=n)tr[x]+=y,x+=x&-x;}
inline int query(int x){int ans=;while(x)ans+=tr[x],x-=x&-x;return ans;}
inline int merge(int l2,int r2,int l1,int r1){
int ans=;
for(int i=l1;i<=r1;++i)ji[rnk[i]]=a[i];
q[]=;
for(int i=;i<=n1;++i)if(ji[i]){
q[++q[]]=ji[i];ji[i]=;
}
int p=;
for(int i=l2;i<=r2;++i)ji[rnk[i]]=a[i];
for(int i=;i<=n1;++i)if(ji[i]){
while(p<=q[]&&(!p||q[p]<=ji[i]))p++;p--;
ans+=p;ji[i]=;
}
return ans;
}
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
int main(){
n=rd();m=rd();
n1=;
for(int i=;i<=n;++i)a[i]=rd(),be[i]=(i-)/n1+,pos[a[i]]=i;
for(int i=;i<=be[n];++i){
int l=(i-)*n1+,r=min(n,i*n1);int top=;
for(int j=l;j<=r;++j)b[++top]=a[j];
sort(b+,b+top+);
for(int j=;j<=top;++j)rnk[pos[b[j]]]=j;
for(int j=l;j<=r;++j){
lef[j]=query(n-a[j]+);
if(j!=l)lef[j]+=lef[j-];
add(n-a[j]+,);tong[n-a[j]+]=;
}
int moss=;
for(int j=n;j>=;--j){
moss+=tong[n-j+];
tag2[i][j]=tag2[i-][j]+moss;
}
for(int j=l;j<=r;++j)add(n-a[j]+,-),tong[n-a[j]+]=;
for(int j=r;j>=l;--j){
rig[j]=query(a[j]);
if(j!=r)rig[j]+=rig[j+];
add(a[j],);tong[a[j]]=;
}
moss=;
for(int j=;j<=n;++j){
moss+=tong[j];
tag1[i][j]=tag1[i-][j]+moss;
}
for(int j=l;j<=r;++j)add(a[j],-),tong[a[j]]=;
}
for(int i=;i<=be[n];++i){
cnt[i][i]=lef[min(n,i*n1)];
for(int j=i+;j<=be[n];++j){
cnt[i][j]=cnt[i][j-];int x=min(n,n1*j);
for(int k=(j-)*n1+;k<=x;++k){
cnt[i][j]+=tag2[j-][a[k]]-tag2[i-][a[k]];
}
cnt[i][j]+=lef[x];
}
}
int l,r;
while(m--){
l=rd();r=rd();l^=ans;r^=ans;
if(l>r)l^=r^=l^=r;ans=;
// if(r>n||l<1){ans=0;puts("0");continue;}
if(be[l]==be[r]){
ans=lef[r];if(l!=(be[l]-)*n1+)ans-=lef[l-],ans-=merge((be[l]-)*n1+,l-,l,r);
}
else{
int st=be[l]+,en=be[r]-;
for(int i=l;i<=be[l]*n1;++i)ans=ans+tag1[en][a[i]]-tag1[st-][a[i]];
for(int i=en*n1+;i<=r;++i)ans=ans+tag2[en][a[i]]-tag2[st-][a[i]];
ans+=cnt[st][en]+rig[l]+lef[r];
ans+=merge(l,(st-)*n1,en*n1+,r);
}
printf("%lld\n",ans);
}
return ;
}

[Ynoi2019模拟赛]Yuno loves sqrt technology I的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. Luogu P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III 分块

    这才是真正的$N\sqrt{N}$吧$qwq$ 记录每个数$vl$出现的位置$s[vl]$,和每个数$a[i]=vl$是第几个$vl$,记为$P[i]$,然后预处理出块$[i,j]$区间的答案$f[i ...

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

    为什么我感觉这题难度虚高啊-- 区间众数的出现次数- 计算器算一下 \(\sqrt 500000 = 708\) 然后我们发现这题的突破口? 考虑分块出来[L,R]块的众数出现个数 用 \(\text ...

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

    题面传送门 qwq 感觉跟很多年前做过的一道题思路差不多罢,结果我竟然没想起那道题?!!所以说我 wtcl/wq 首先将 \(a_i\) 离散化. 如果允许离线那显然一遍莫队就能解决,复杂度 \(n\ ...

  10. 洛谷 P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I(分块+卡常)

    洛谷题面传送门 zszz,lxl 出的 DS 都是卡常题( 首先由于此题强制在线,因此考虑分块,我们那么待查询区间 \([l,r]\) 可以很自然地被分为三个部分: 左散块 中间的整块 右散块 那么这 ...

随机推荐

  1. mysql触发器new和old

    下面为您介绍mysql触发器new old的相关知识,供您参考学习,如果您在mysql触发器方面遇到过类似的问题,不妨一看,相信对您会有所帮助. mysql触发器new old: "NEW ...

  2. java类的继承(基础)

    ---恢复内容开始--- 这篇随笔和大家讲讲java中类的继承是什么?希望对你们有所帮助. 目录 一.java继承是什么? 二.为什么使用java继承 三.java继承的实现 1.1  java继承的 ...

  3. 对HTML5标签的认识(四)

    这篇随笔讲讲HTML5中的表单和表单的一些元素 一.表单的作用是什么? 概念:表单在网页中主要是负责对数据信息的采取,表单一共分成三个部分: 1.表单的标签:这里面包含了处理表单的数据所用CGI程序以 ...

  4. JVM虚拟机基本概念

    一.JVM运行时数据区域1.1.程序计数器 一块较小的内存空间,当前线程所执行的字节码指示器.每个线程有一个独立的程序计数器1.2.Java虚拟机栈 线程私有,生命周期与线程相同 每个方法在执行时会创 ...

  5. npm --save-dev --save 的区别

    我们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如: --save-dev(-D) --save(-S) 在 package.j ...

  6. 学习day02

    day021.结构标记 ***** 做布局 1.<header>元素 <header></header> ==> <div id="heade ...

  7. android 记一次解决键盘遮挡问题

    文章链接:https://mp.weixin.qq.com/s/1gkMtLu0BTXOUOj6isDjUw 日常android开发过程中,会遇到编辑框输入内容弹出软键盘,往往会出现键盘遮挡内容,或者 ...

  8. Linux安装配置Mariadb

    一.安装数据库Mariadb 参考:http://blog.51cto.com/12173069/2047746 从最新版本的linux系统开始,默认的是 Mariadb而不是mysql! 使用系统自 ...

  9. [20190417]隐含参数_SPIN_COUNT.txt

    [20190417]隐含参数_SPIN_COUNT.txt--//在探究latch spin计数之前,先简单探究_SPIN_COUNT.实际上oracle现在版本latch spin的数量不再是200 ...

  10. 如何自己制作CHM电子书?

    软件介绍: EasyCHM 非常适合个人和单位制作高压缩比的有目录.索引,同时具有全文检索及高亮显示搜索结果的网页集锦.CHM格式的帮助文件.专业的产品说明书.公司介绍.文章集锦.CHM电子书等等. ...