[Ynoi2019模拟赛]Yuno loves sqrt technology I
题目描述
给你一个长为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的更多相关文章
- [Ynoi2019模拟赛]Yuno loves sqrt technology II(二次离线莫队)
二次离线莫队. 终于懂了 \(lxl\) 大爷发明的二次离线莫队,\(\%\%\%lxl\) 二次离线莫队,顾名思义就是将莫队离线两次.那怎么离线两次呢? 每当我们将 \([l,r]\) 移动右端点到 ...
- [Luogu5048] [Ynoi2019模拟赛]Yuno loves sqrt technology III[分块]
题意 长为 \(n\) 的序列,询问区间众数,强制在线. \(n\leq 5\times 10^5\). 分析 考虑分块,暴力统计出整块到整块之间的众数次数. 然后答案还可能出现在两边的两个独立的块中 ...
- [luogu5048] [Ynoi2019模拟赛] Yuno loves sqrt technology III
题目链接 洛谷. Solution 思路同[BZOJ2724] [Violet 6]蒲公英,只不过由于lxl过于毒瘤,我们有一些更巧妙的操作. 首先还是预处理\(f[l][r]\)表示\(l\sim ...
- [洛谷P5048][Ynoi2019模拟赛]Yuno loves sqrt technology III
题目大意:有$n(n\leqslant5\times10^5)$个数,$m(m\leqslant5\times10^5)$个询问,每个询问问区间$[l,r]$中众数的出现次数 题解:分块,设块大小为$ ...
- 洛谷P5048 [Ynoi2019模拟赛]Yuno loves sqrt technology III(分块)
传送门 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 用蒲公英那个分块的方法做结果两天没卡过去→_→ 首先我们分块,预处理块与块之间的答案,然后每次询问的时候拆成整块和两边剩下的元素 整块的答案很简 ...
- [Ynoi2019模拟赛]Yuno loves sqrt technology II
题目大意: 给定一个长为\(n\)的序列,\(m\)次询问,每次查询一个区间的逆序对数. 32MB. 解题思路: 出题人题解 众所周知lxl是个毒瘤,Ynoi道道都是神仙题 二次离线莫队. 对于每个区 ...
- 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 ...
- P5048 [[Ynoi2019模拟赛]Yuno loves sqrt technology III]
为什么我感觉这题难度虚高啊-- 区间众数的出现次数- 计算器算一下 \(\sqrt 500000 = 708\) 然后我们发现这题的突破口? 考虑分块出来[L,R]块的众数出现个数 用 \(\text ...
- 洛谷 P5048 - [Ynoi2019 模拟赛] Yuno loves sqrt technology III(分块)
题面传送门 qwq 感觉跟很多年前做过的一道题思路差不多罢,结果我竟然没想起那道题?!!所以说我 wtcl/wq 首先将 \(a_i\) 离散化. 如果允许离线那显然一遍莫队就能解决,复杂度 \(n\ ...
- 洛谷 P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I(分块+卡常)
洛谷题面传送门 zszz,lxl 出的 DS 都是卡常题( 首先由于此题强制在线,因此考虑分块,我们那么待查询区间 \([l,r]\) 可以很自然地被分为三个部分: 左散块 中间的整块 右散块 那么这 ...
随机推荐
- [TCP/IP] 网络层-简单查看路由表
使用抓包工具排除网络故障:1.如果一台计算机在网络上发广播包,广播的mac地址是全ff,就有可能堵塞2.使用抓包工具,检测广播包和多播包 网络畅通的条件:数据包有去有回1.路由器使用路由表找到目标网段 ...
- I/O输出流基础之FileOutputStream
OutputStream:是所有字节输出流的父类,其作用是:用这个流把网络数据(getOutputStream()),或者内存中的字节数组数据写到文件系统中文件系统(FileOutputStream) ...
- java实现 批量转换文件编码格式
一.场景说明 不知道大家有没有遇到过之前项目是GBK,现在需要全部换成UTF-8的情况.反正我是遇到了. eclipse可以改变项目的编码格式,但是文件如果直接转换的话里面的中文就会全部乱码,需要先复 ...
- 阿里巴巴矢量图标库(Iconfont)-利于UI和前端的搭配
前端时间,做一个小网站的时候,需要用到很多小图标,UI设计好之后不知道如何使用,如果使用图片那会很麻烦,相信一些前端更喜欢iconfont这样的标签直接调用,这样包括颜色和大小以及使用都更方便快捷,于 ...
- ASP.Net Core开发(踩坑)指南
ASP.NET与ASP.NET Core很类似,但它们之间存在一些细微区别以及ASP.NET Core中新增特性的使用方法,在此之前也写过一篇简单的对比文章ASP.NET MVC应用迁移到ASP.NE ...
- 解决Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile
原因: 由于项目所需jdk版本和你当前使用的jdk版本不一致导致的,因为我项目的pom.xml中定义了java版本为1.8,但是我实际idea中run这个项目却是1.7 解决方案: 更换当前jdk版本 ...
- django 问题综合
orm部分 本篇文章我会持续更新,把开发中遇到的一切orm相关的问题都放在这里 mysql索引报错 使用django 的orm,数据库用的mysql,在使用makemigrations和migrate ...
- Java基础系列--03_Java中的方法描述
方法 (1)方法的定义:就是完成特定功能的代码块. 注意:在很多语言里面有函数的定义,而在Java中,函数被称为方法. (2)格式: 修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2 ...
- Python 爬虫基础Selenium
https://blog.csdn.net/weixin_36279318/article/details/79475388
- windows 10 防火墙设置规则:允许特定ip端口
本例中以如何设置ip为10.242.62.239的电脑通过3306端口访问我的电脑 为例 1, 打开防火墙高级设置,如图所示,操作如下 入站规则->新建规则->自定义->下一步 2, ...