Codeforces785E - Anton and Permutation
Description
对一个长度为\(n(n\leq2\times10^5)\)的数列\(a\)进行\(m(m\leq5\times10^4)\)次操作,数列初始时为\(\{1,2,...,n\}\)。每次操作交换数列中的两个数\(a_L\)和\(a_R\),并询问此时数列\(a\)中的逆序对数。
Solution
交换\(a_L\)和\(a_R\)时,会影响逆序对数的只有下标在\((L,R)\)之间,数值在\(a_L\)和\(a_R\)之间的数(钦定\(L<R\))。设这样的数有\(k\)个,那么若\(a_L<a_R\),逆序对数会增加\(2k+1\);若\(a_L>a_R\),逆序对数会减少\(2k+1\)。
所以只要使用一种数据结构,支持单点修改和查询区间内数值在某个范围内的数的个数。分块即可解决这个问题。维护每个块内的数有序,那么就可以通过二分查找以\(O(log\sqrt n)\)求出块内满足条件的数的个数。对于修改,修改之后将所在块再次排序即可。
时间复杂度\(O(m\sqrt nlog\sqrt n)。\)
Code
//Anton and Permutation
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long lint;
inline char gc()
{
static char now[1<<16],*S,*T;
if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
return *S++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
int const N=2e5+1e3;
int n,m,n0,a[N];
int blk[N],fr[N],to[N],b[N];
int query(int t,int x,int y)
{
int L=upper_bound(b+fr[t],b+to[t]+1,x)-b;
int R=lower_bound(b+fr[t],b+to[t]+1,y)-b-1;
return R-L+1;
}
void update(int t)
{
for(int i=fr[t];i<=to[t];i++) b[i]=a[i];
sort(b+fr[t],b+to[t]+1);
}
int main()
{
n=read(),m=read(); n0=sqrt(n);
for(int i=1;i<=n;i++) a[i]=b[i]=i;
for(int i=1;i<=n;i++) blk[i]=(i-1)/n0+1;
for(int i=1;i<=blk[n];i++) fr[i]=(i-1)*n0+1,to[i]=i*n0;
to[blk[n]]=n;
lint ans=0;
for(int i=1;i<=m;i++)
{
int L=read(),R=read(); if(L>R) swap(L,R);
if(L==R) {printf("%lld\n",ans); continue;}
int x=a[L],y=a[R]; lint res=0,f=1;
if(x>y) swap(x,y),f=-1;
if(blk[L]==blk[R]) for(int i=L;i<=R;i++) res+=(x<a[i]&&a[i]<y);
else
{
for(int i=L;i<=to[blk[L]];i++) res+=(x<a[i]&&a[i]<y);
for(int t=blk[L]+1;t<=blk[R]-1;t++) res+=query(t,x,y);
for(int i=fr[blk[R]];i<=R;i++) res+=(x<a[i]&&a[i]<y);
}
ans+=2*res*f; if(a[L]<a[R]) ans++; else ans--;
swap(a[L],a[R]); update(blk[L]),update(blk[R]);
printf("%lld\n",ans);
}
return 0;
}
P.S.
要用long long
来保存逆序对数。
存在\(L=R\)的情况,可以特判一下。
Codeforces785E - Anton and Permutation的更多相关文章
- Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...
- Anton and Permutation
Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input standa ...
- Codeforces 785 E. Anton and Permutation(分块,树状数组)
Codeforces 785 E. Anton and Permutation 题目大意:给出n,q.n代表有一个元素从1到n的数组(对应索引1~n),q表示有q个查询.每次查询给出两个数l,r,要求 ...
- Codeforces 785E. Anton and Permutation
题目链接:http://codeforces.com/problemset/problem/785/E 其实可以CDQ分治... 我们只要用一个数据结构支持单点修改,区间查询比一个数大(小)的数字有多 ...
- [CF785E]Anton and Permutation
题目大意:有一串数为$1\sim n(n\leqslant2\times10^5)$,$m(m\leqslant5\times10^4)$次询问,每次问交换位置为$l,r$的两个数后数列中逆序对的个数 ...
- Codeforces 785E Anton and Permutation(分块)
[题目链接] http://codeforces.com/contest/785/problem/E [题目大意] 一个1到n顺序排列的数列,每次选择两个位置的数进行交换,求交换后的数列的逆序对数 [ ...
- CodeForces 785E Anton and Permutation 分块
题意: 有一个\(1 \sim n\)的排列\(A\),有\(q\)个询问: 交换任意两个元素的位置,求交换之后排列的逆序数 分析: 像这种不太容易用线段树,树状数组维护的可以考虑分块 每\(\sqr ...
- 【codeforces 785E】Anton and Permutation
[题目链接]:http://codeforces.com/problemset/problem/785/E [题意] 给你一个初始序列1..n顺序 然后每次让你交换任意两个位置上面的数字; 让你实时输 ...
- 题解 CF785E 【Anton and Permutation】
考虑用分块解决这个题,一次交换对当前逆序对个数的影响是,加上两倍的在区间\([l+1,r-1]\)中比\(a_r\)小的元素个数,减去两倍的在区间\([l+1,r-1]\)中比\(a_l\)小的元素个 ...
随机推荐
- 控制器没有足够的带宽可利用为USB大容量存储设备的解决方法
伴随网盘时代的没落,最近刚入手了一个移动硬盘.现在的移动硬盘都是USB3.0,传输速度比USB2.0要快很多.但是链接笔记本电脑后发现传输速度在20MB/s左右,跟USB2.0速度差不多,并不能达到传 ...
- 使用sed替换一行内多个括号内的值
1. 括号在同一行 # cat test2good morning (good afternoon) (good evening) (goodgood) (good morning) # cat se ...
- mysql(4)—— 表连接查询与where后使用子查询的性能分析。
子查询就是在一条查询语句中还有其它的查询语句,主查询得到的结果依赖于子查询的结果. 子查询的子语句可以在一条sql语句的FROM,JOIN,和WHERE后面,本文主要针对在WHERE后面使用子查询与表 ...
- Java并发系列[4]----AbstractQueuedSynchronizer源码分析之条件队列
通过前面三篇的分析,我们深入了解了AbstractQueuedSynchronizer的内部结构和一些设计理念,知道了AbstractQueuedSynchronizer内部维护了一个同步状态和两个排 ...
- https原理及实践
转载请注明出处 安全知识 网络安全问题 数据机密性 在网络传输数据信息时,对数据的加密是至关重要的,否则所有传输的数据都是可以随时被第三方看到,完全没有机密性可言. 数据机密性解决问题思路 利用算法 ...
- mkdir与mkdirs的区别
mkdir与mkdirs的区别 项目中需要在代码中读取或创建文件保存路径,用到了mkdir,查看还有个mkdirs方法,这里记录一下两者的区别. 1.关于两者的说明如下: boolean mkdir( ...
- JAVA并发编程学习笔记------基础构建模块
一.并发容器:ConcurrentHashMap:1.分段锁机制: 任意数量的读取线程可以并发的访问map,执行读取操作的线程和执行写入操作的线程可以并发的访问Map,并且一定数量的写入线程可以并发的 ...
- Base-64编码介绍
Base-64编码保证了二进制数据的安全 Base-64编码可以将任意一组字节转换为较长的常见文本字符序列,从而可以合法地作为首部字段值.Base-64编码将用户输入或二进制数据,打包成一种安全格式, ...
- NIO基础篇(二)
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 传统的 ...
- 从UUID想到的
1.UUID的定义 通用唯一标识符(UUID)被设计成一个在时间和空间上都独一无二的数字,常被用作唯一性标识. UUID是一个由5位十六进制数的字符串表示的128比特数字,其格式为 aaaaaaaa- ...