CF785CAnton and Permutation(分块 动态逆序对)
Anton likes permutations, especially he likes to permute their elements. Note that a permutation of n elements is a sequence of numbers {a1, a2, ..., an}, in which every number from 1 to n appears exactly once.
One day Anton got a new permutation and started to play with it. He does the following operation q times: he takes two elements of the permutation and swaps these elements. After each operation he asks his friend Vanya, how many inversions there are in the new permutation. The number of inversions in a permutation is the number of distinct pairs (i, j) such that 1 ≤ i < j ≤ n and ai > aj.
Vanya is tired of answering Anton's silly questions. So he asked you to write a program that would answer these questions instead of him.
Initially Anton's permutation was {1, 2, ..., n}, that is ai = i for all i such that 1 ≤ i ≤ n.
Input
The first line of the input contains two integers n and q (1 ≤ n ≤ 200 000, 1 ≤ q ≤ 50 000) — the length of the permutation and the number of operations that Anton does.
Each of the following q lines of the input contains two integers li and ri (1 ≤ li, ri ≤ n) — the indices of elements that Anton swaps during the i-th operation. Note that indices of elements that Anton swaps during the i-th operation can coincide. Elements in the permutation are numbered starting with one.
Output
Output q lines. The i-th line of the output is the number of inversions in the Anton's permutation after the i-th operation.
Example
5 4
4 5
2 4
2 5
2 2
1
4
3
3
2 1
2 1
1
6 7
1 4
3 5
2 3
3 3
3 6
2 1
5 1
5
6
7
7
10
11
8
Note
Consider the first sample.
After the first Anton's operation the permutation will be {1, 2, 3, 5, 4}. There is only one inversion in it: (4, 5).
After the second Anton's operation the permutation will be {1, 5, 3, 2, 4}. There are four inversions: (2, 3), (2, 4), (2, 5) and (3, 4).
After the third Anton's operation the permutation will be {1, 4, 3, 2, 5}. There are three inversions: (2, 3), (2, 4) and (3, 4).
After the fourth Anton's operation the permutation doesn't change, so there are still three inversions.
题意:
初始数列,a[]为顺序排列。问每次交换u,v两个位置的数字后,逆序对数量。
由于数状数组解决逆序对是离线操作,不支持交换操作(就我所知是如此)。反正不好快速查询u,v位置的数和之间的数大小关系。
所以用分块乱搞,如果u,v距离不远,暴力即可,如果太远,可以用分块好的有序数组快速得到排名关系。每一次操作O(lg+sqrt)。
感觉不难实现,而且马上打CF了,所以难得写一遍了。
不过有序vector的删除和加入以前倒是没有实现过,get。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#define ps push_back
#define Siz(x) (int)x.size()
using namespace std;
typedef long long LL;
LL ans = 0LL;
const int maxn = + ;
int n,q; //n个数,m个操作
int num; //num个块
int block; // 块的长度
int L[maxn], R[maxn]; //每个块的左右边界
int a[maxn]; //n个数,用与单个比较
int belong[maxn]; //位置属于哪一块
vector<int> bit[maxn]; //每个块,用于lower_bound快速找个数。
void init(){
block=sqrt(n);
num=(n-)/block+;
for (int i=;i<=num;i++){
L[i]=(i-)*block+;
R[i]=i*block;
} R[num]=n; //修改细节
for(int i=;i<=n;i++)
belong[i]=(i-)/block + ;
for(int i=;i<=num;i++)
for (int j=L[i];j<=R[i];j++)
bit[i].ps(j); //每一块的有序序列
}
int query(int l,int r,int v){
if (l>r) return ;
int ans=;
if(belong[l]==belong[r]){
for(int i=l;i<=r;++i)
if(a[i]<v) ++ans;
return ans;
}
int id=belong[l];
for(int i=l;i<=R[id];++i){
if(a[i]<v) ans++;
}
for(int i=belong[l]+;i<=belong[r]-;i++){
int p2=lower_bound(bit[i].begin(),bit[i].end(),v)-bit[i].begin();
ans+=p2;
}
id=belong[r];
for(int i=L[id];i<=r;i++){
if(a[i]<v) ans++;
}
return ans;
}
void update(int l,int r){
int uu=a[l];
int vv=a[r];
int id=belong[l];
bit[id].erase(lower_bound(bit[id].begin(),bit[id].end(),uu));//删去。
bit[id].insert(upper_bound(bit[id].begin(),bit[id].end(),vv),vv);//加入
id = belong[r];
bit[id].erase(lower_bound(bit[id].begin(),bit[id].end(),vv));
bit[id].insert(upper_bound(bit[id].begin(),bit[id].end(),uu),uu);
swap(a[l],a[r]);
}
int main(){
scanf("%d %d",&n, &q);
for (int i=;i<=n;i++) a[i] = i;
init();
while(q--){
int u,v;
scanf("%d%d",&u,&v);
if(u==v){
printf("%lld\n",ans);
continue;
}
if(u>v) swap(u,v);
int t1=query(u+,v-,a[u]);//期间比左边小的
int t2=v--u-+-t1;//期间比左边大的
ans-=t1; ans+=t2;
t1=query(u+,v-,a[v]);
t2=v--u-+-t1;
ans+=t1; ans-=t2;
if(a[u]<a[v])++ans;
else ans--;
printf("%lld\n",ans);
update(u,v);
}
return ;
}
CF785CAnton and Permutation(分块 动态逆序对)的更多相关文章
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- BZOJ 3295: [Cqoi2011]动态逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3865 Solved: 1298[Submit][Sta ...
- 【Luogu1393】动态逆序对(CDQ分治)
[Luogu1393]动态逆序对(CDQ分治) 题面 题目描述 对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i < j的有序对(i,j)的个数.你需要计算出一个序 ...
- 【BZOJ3295】动态逆序对(线段树,树状数组)
[BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...
- bzoj3295[Cqoi2011]动态逆序对 树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5987 Solved: 2080[Submit][Sta ...
- cdq分治(hdu 5618 Jam's problem again[陌上花开]、CQOI 2011 动态逆序对、hdu 4742 Pinball Game、hdu 4456 Crowd、[HEOI2016/TJOI2016]序列、[NOI2007]货币兑换 )
hdu 5618 Jam's problem again #include <bits/stdc++.h> #define MAXN 100010 using namespace std; ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- P3157 [CQOI2011]动态逆序对
P3157 [CQOI2011]动态逆序对 https://www.luogu.org/problemnew/show/P3157 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai&g ...
- 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)
3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...
随机推荐
- robotframework安装appium
安装: Appium-Python-Client,在运行的cmd下输入:pip install Appium-python-Client 安装:robotframework-appiumlibrary ...
- Chrome自带恐龙小游戏的源码研究(五)
在上一篇<Chrome自带恐龙小游戏的源码研究(四)>中实现了障碍物的绘制及移动,从这一篇开始主要研究恐龙的绘制及一系列键盘动作的实现. 会眨眼睛的恐龙 在游戏开始前的待机界面,如果仔细观 ...
- python学习(七)字典学习
#!/usr/bin/python # 字典 # 当时学java的时候, 语言基础就学了好久, 然后是各种API, 最后才是集合 # 键值对, 可变 # 1. 映射操作 D = {'food' : ' ...
- Kindeditor上传图片回显不出来
原因之一: 图片成功上传但是回显不出来,这个时候,要检查返回的图片地址是否加了http://这个玩意,不然会将原来的头加上图片返回地址.
- [Linux] 网络
如何在网络中标识一台计算机 IP 多个程序如何不冲突 通信端口 不同的计算机如何通信 协议 IP A类:0+7位网络号+24位主机号,可用网络2^7-2个,每个网络可容纳2^24-2个主机 B类:10 ...
- 不依赖外部js es 库 实现 点击内容 切换
<!DOCTYPE html> <html lang="zh-cmn-Hans"> <head> <meta http-equiv=&qu ...
- Android笔记之引用aar
把要引用的aar文件复制到目录app\libs中(我要引用的aar名为xybigdatasdk-release-out2.2.6.aar) 在build.gradle (Module: app)中添加 ...
- Wix Burn运行64位dism.exe的问题
主要的问题是Burn是一个32位程序,在64位机器上它启动的进程都会被重定向到wow64目录下,也就是说它运行的dism.exe最终会是32位的.解决的方法就是用wix提供的QtExec64CmdLi ...
- python cookbook第三版学习笔记七:python解析csv,json,xml文件
CSV文件读取: Csv文件格式如下:分别有2行三列. 访问代码如下: f=open(r'E:\py_prj\test.csv','rb') f_csv=csv.reader(f) for f in ...
- ubuntun下安装sublime text
Sublime Text 3 是一款轻量级.跨平台的文本编辑器.可安装在ubuntu,Windows和MAC OS X上高级文本编辑软件,有一个专有的许可证,但该程序也可以免费使用,无需做逆向工程.如 ...