[CF785E]Anton and Permutation
题目大意:有一串数为$1\sim n(n\leqslant2\times10^5)$,$m(m\leqslant5\times10^4)$次询问,每次问交换位置为$l,r$的两个数后数列中逆序对的个数。
题解:发现交换位置为$l,r$的数后,逆序对的变化只和区间$(l,r)$内的数与$s_l,s_r$的大小关系有关,设$S_i$表示区间$(l,r)$中比$s_i$小的数,$B_i$表示区间$(l,r)$中比$s_i$大的数,$ans'=ans+S_r-B_r-S_l+B_l$。设$len=r-l-1$,$ans'=ans+S_r-(len-S_r)-S_l+(len-S_l)=ans+2(S_r-S_l)$。
考虑分块,设块大小为$S$,在块内排序,在边角处暴力,在整块处二分查找位置,询问的复杂度是$O(2S+\dfrac n S\log_2S)$;修改为二分处位置直接插入或删除,复杂度$O(4S)$,所以当$S$略大于$\sqrt n$时最优。(反正我懒得算,随便猜一个)
卡点:
1. 计算$2(S_r-S_l)$时使用了位运算,当$S_r-S_l$为负数时出锅
2. 最开始块大小设成了$512$,计算块时用了$2^8$
C++ Code:
#include <algorithm>
#include <cstdio>
#include <vector>
#define maxn 200010
const int BSZ = 1000, BNUM = maxn / BSZ + 10; int n, m;
long long ans;
int L[BNUM], R[BNUM], bel[maxn], s[maxn];
std::vector<int> V[BNUM]; int query(int l, int r, int x) {
if (l > r) return 0;
const int lb = bel[l], rb = bel[r];
int res = 0;
if (lb == rb) for (int i = l; i <= r; ++i) res += s[i] < x;
else {
for (int i = l; i <= R[lb]; ++i) res += s[i] < x;
for (int i = lb + 1; i < rb; ++i) res += std::upper_bound(V[i].begin(), V[i].end(), x) - V[i].begin();
for (int i = L[rb]; i <= r; ++i) res += s[i] < x;
}
return res;
} int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) V[bel[i] = i / BSZ + 1].push_back(s[i] = i);
const int B = bel[n];
for (int i = 1; i <= B; ++i) {
L[i] = (i - 1) * BSZ;
R[i] = L[i] + BSZ - 1;
}
L[1] = 1, R[B] = n;
while (m --> 0) {
int l, r;
scanf("%d%d", &l, &r);
if (l == r) {
printf("%lld\n", ans);
continue;
}
if (l > r) std::swap(l, r);
const int lb = bel[l], rb = bel[r]; ans += (query(l + 1, r - 1, s[r]) - query(l + 1, r - 1, s[l])) * 2;
ans += (s[l] < s[r]) ? 1 : -1;
printf("%lld\n", ans); if (lb != rb) {
V[lb].erase(std::lower_bound(V[lb].begin(), V[lb].end(), s[l]));
V[lb].insert(std::upper_bound(V[lb].begin(), V[lb].end(), s[r]), s[r]);
V[rb].erase(std::lower_bound(V[rb].begin(), V[rb].end(), s[r]));
V[rb].insert(std::upper_bound(V[rb].begin(), V[rb].end(), s[l]), s[l]);
}
std::swap(s[l], s[r]);
}
return 0;
}
[CF785E]Anton and Permutation的更多相关文章
- Codeforces785E - Anton and Permutation
Portal Description 对一个长度为\(n(n\leq2\times10^5)\)的数列\(a\)进行\(m(m\leq5\times10^4)\)次操作,数列初始时为\(\{1,2,. ...
- 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,要求 ...
- 题解 CF785E 【Anton and Permutation】
考虑用分块解决这个题,一次交换对当前逆序对个数的影响是,加上两倍的在区间\([l+1,r-1]\)中比\(a_r\)小的元素个数,减去两倍的在区间\([l+1,r-1]\)中比\(a_l\)小的元素个 ...
- Codeforces 785E. Anton and Permutation
题目链接:http://codeforces.com/problemset/problem/785/E 其实可以CDQ分治... 我们只要用一个数据结构支持单点修改,区间查询比一个数大(小)的数字有多 ...
- 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顺序 然后每次让你交换任意两个位置上面的数字; 让你实时输 ...
随机推荐
- Java 数字用二进制表示,以及原码,反码,补码、负数的二进制表示
首先我们要对原码.反码和补码有个了解: 1.所谓原码就是二进制定点表示法,即最高位为符号位,"0"表示正,"1"表示负,其余位表示数值的大小. 2.反码表示法规 ...
- 11、Java并发编程:并发容器之CopyOnWriteArrayList
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
- 【WXS数据类型】Function
属性: 名称 值类型 说明 [Function].constructor [String] 返回值为“Function”,表示类型的结构字符串 [Function].length [Number] 返 ...
- JVM--Java类加载机制
一.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其存放在运行时数据区的方法区内,然后在java堆区创建一个java.lang.Class对象,用来封装类在方法区内 ...
- leetcode-对称二叉树
对称二叉树 给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的. 1 / \ 2 2 / \ / \ 3 4 4 3 但是下面这个 [1,2,2, ...
- 【转载】IOS之禁用UIWebView的默认交互行为
原文地址 :IOS之禁用UIWebView的默认交互行为 http://my.oschina.net/hmj/blog/111344 UIKit提供UIWebView组件,允许开发者在App中嵌入We ...
- Python版本切换和Pip安装
Python版本切换 现在常用的linux系统中都会默认携带python运行环境,在ubuntu 16.04 和centos 7.3中携带有Python 2.7 和Python3.5两个版本, 默认使 ...
- numpy切片和布尔型索引
numpy 标签(空格分隔): numpy 数据挖掘 切片 数组切片是原始数组的视图.这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上 In [16]: arr Out[16]: arr ...
- tendermint学习
怎么把两个节点变成验证节点 1. 两个节点分别启动 2. 两个节点同时把自己的公钥信息添加到对方的创始快配置文件中,总而言之,创始块一样 3. unsafe_reset_priv_validator ...
- BZOJ 4361 isn 容斥+dp+树状数组
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4361 题意概述: 给出一个长度为N的序列A(A1,A2...AN).如果序列A不是非降的 ...