题目大意:有一串数为$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的更多相关文章

  1. Codeforces785E - Anton and Permutation

    Portal Description 对一个长度为\(n(n\leq2\times10^5)\)的数列\(a\)进行\(m(m\leq5\times10^4)\)次操作,数列初始时为\(\{1,2,. ...

  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 ...

  3. Anton and Permutation

    Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input standa ...

  4. Codeforces 785 E. Anton and Permutation(分块,树状数组)

    Codeforces 785 E. Anton and Permutation 题目大意:给出n,q.n代表有一个元素从1到n的数组(对应索引1~n),q表示有q个查询.每次查询给出两个数l,r,要求 ...

  5. 题解 CF785E 【Anton and Permutation】

    考虑用分块解决这个题,一次交换对当前逆序对个数的影响是,加上两倍的在区间\([l+1,r-1]\)中比\(a_r\)小的元素个数,减去两倍的在区间\([l+1,r-1]\)中比\(a_l\)小的元素个 ...

  6. Codeforces 785E. Anton and Permutation

    题目链接:http://codeforces.com/problemset/problem/785/E 其实可以CDQ分治... 我们只要用一个数据结构支持单点修改,区间查询比一个数大(小)的数字有多 ...

  7. Codeforces 785E Anton and Permutation(分块)

    [题目链接] http://codeforces.com/contest/785/problem/E [题目大意] 一个1到n顺序排列的数列,每次选择两个位置的数进行交换,求交换后的数列的逆序对数 [ ...

  8. CodeForces 785E Anton and Permutation 分块

    题意: 有一个\(1 \sim n\)的排列\(A\),有\(q\)个询问: 交换任意两个元素的位置,求交换之后排列的逆序数 分析: 像这种不太容易用线段树,树状数组维护的可以考虑分块 每\(\sqr ...

  9. 【codeforces 785E】Anton and Permutation

    [题目链接]:http://codeforces.com/problemset/problem/785/E [题意] 给你一个初始序列1..n顺序 然后每次让你交换任意两个位置上面的数字; 让你实时输 ...

随机推荐

  1. 华为LiteOS系统使用-任务调度函数-第一篇

    1.最近项目遇到华为的LiteOS小型操作系统,使用学习 2. 先打开一个工程LiteOS_Kernel-master\projects\LPC824_LITE_KEIL 3. main.c里面2个关 ...

  2. jmeter开发自己的sampler插件

    1. 新建maven工程 2.pom文件引入jmeter的核心包 <project xmlns="http://maven.apache.org/POM/4.0.0" xml ...

  3. jmeter基础之录制篇

    一.前言 jmeter如今被越来越多人喜爱的一款测试工具,相比于loadrunner它体积特轻便.jmeter不仅用来做单接口测试,压测还能做性能,主要是一款开源的,可以写一个你需要的插件功能再添加里 ...

  4. Shader-水流效果

    效果图:(贴图类似于泥石流) 代码: Shader "CookbookShaders/Chapter02/ScrollingUVs" { Properties { _MainTin ...

  5. Consul 简介

    Consul包含很多组件,总体来数,Consul是一种服务发现和配置工具. 服务发现:一个客户端提供自己的服务,例如api服务,或者mysql服务,另一个客户端就可以利用Consul通过DNS或者ht ...

  6. Bootstrap栅格系统基本使用

    1.什么是栅格系统: 在Bootstrap中,它提供了一套响应式.移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列.栅格系统用于通过一系列的行(row ...

  7. spark集群安装部署

    通过Ambari(HDP)或者Cloudera Management (CDH)等集群管理服务安装和部署在此不多介绍,只需要在界面直接操作和配置即可,本文主要通过原生安装,熟悉安装配置流程. 1.选取 ...

  8. 百度翻译api 实现简易微信翻译小程序

    介绍 口袋翻译 口袋翻译 微信小程序 翻译功能 含7类语言的相互翻译 包含最近10条的翻译历史回溯功能 微信搜索:简e翻译 功能展示   使用百度翻译api需要申请 appid 与 key 并在 ap ...

  9. Learning Spatial-Temporal Regularized Correlation Filters for Visual Tracking---随笔

    Learning Spatial-Temporal Regularized Correlation Filters for Visual Tracking DCF跟踪算法因边界效应,鲁棒性较差.SRD ...

  10. C++ 学习笔记之——STL 库 vector

    vector 是一种顺序容器,可以看作是可以改变大小的数组. 就像数组一样,vector 占用连续的内存地址来存储元素,因此可以像数组一样用偏移量来随机访问,但是它的大小可以动态改变,容器会自动处理内 ...