题目描述

给你一个长为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. 从零开始学安全(四十二)●利用Wireshark分析ARP协议数据包

    wireshark:是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换,是目前 ...

  2. 调用链监控 CAT 之 URL埋点实践

    URL监控埋点作用 一个http请求来了之后,会自动打点,能够记录每个url的访问情况,并将以此请求后续的调用链路串起来,可以在cat上查看logview 可以在cat Transaction及Eve ...

  3. Spring Boot 入门(五):集成 AOP 进行日志管理

    本篇文章是接着 Spring boot 入门(四):集成 Shiro 实现登陆认证和权限管理写的,按照前面几篇博客的教程,可以搭建一个简单的项目,主要包含了 Pagehelper+MyBatis 分页 ...

  4. Nginx Windows详细安装部署教程

    一.Nginx简介 Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Ramble ...

  5. FreeNas搭建踩坑指南(三)

    0x00 Dell R730 无法编辑阵列卡Raid FreeNas和Windows Server都做成了uefi启动,装之前删掉了数据盘配置,系统装好后重启发现无法进入阵列卡编辑 0x01 解决方案 ...

  6. C# 中一些类关系的判定方法

    1.  IsAssignableFrom实例方法 判断一个类或者接口是否继承自另一个指定的类或者接口. public interface IAnimal { } public interface ID ...

  7. VR一体机如何退出FFBM(QFIL)

    前文介绍了通过fastboot命令擦除misc分区,从而退出FFBM的方法.这个方法比较简便,但有不灵的时候,fastboot erase misc命令执行失败,如下图所示. erasing 'mis ...

  8. Testlink1.9.17使用方法( 第四章 测试需求管理 )

    第四章 测试需求管理 QQ交流群:585499566 需求规格说明书是我们开展测试的依据.首先,我们可以对项目(产品)的需求规格说明书进行分解和整理,将其拆分为多个需求,一个项目可以包含多个需求,一个 ...

  9. EntityFramework Code-First—领域类配置之DataAnnotations

    本文出自:https://www.cnblogs.com/tang-tang/p/5510574.html 一.摘要 EF Code-First提供了一个可以用在领域类或其属性上的DataAnnota ...

  10. block的注意点

    1). 在block内部使用外部指针且会造成循环引用情况下,需要用__week修饰外部指针: __weak typeof(self) weakSelf = self; 2). 在block内部如果调用 ...