浅谈分块:https://www.cnblogs.com/AKMer/p/10369816.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2141

第一次的答案可以直接用树状数组求。

如果交换\(pos_1\)和\(pos_2\),那么显然我不需要管\([1,pos_1-1]\)和\([pos_2+1,n]\)。

对于\([pos_1+1,pos_2-1]\)之间的每个数\(v_i\)

\(v_i<v_{pos_1}\),答案减一;\(v_i>v_{pos_1}\),答案加一;\(v_i<v_{pos_2}\),答案加一,\(v_i>v_{pos_2}\),答案减一。

对于每个块我用一个树状数组维护块内权值个数。整个的块直接查找有多少小于或者大于某个值的数的个数,零散的直接暴力扫。

时间复杂度:\(O(NlogN+M\sqrt{N}logN)\)

空间复杂度:\(O(N\sqrt{n})\)

代码如下:

  1. #include <cmath>
  2. #include <cstdio>
  3. #include <algorithm>
  4. using namespace std;
  5. #define low(i) ((i)&(-(i)))
  6. const int maxn=2e4+5;
  7. int L[145],R[145];
  8. int n,m,cnt,block,ans;
  9. int tmp[maxn],v[maxn],bel[maxn];
  10. int read() {
  11. int x=0,f=1;char ch=getchar();
  12. for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
  13. for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
  14. return x*f;
  15. }
  16. struct Tree_array {
  17. int c[maxn];
  18. void add(int pos,int num) {
  19. for(int i=pos;i<=cnt;i+=low(i))
  20. c[i]+=num;
  21. }
  22. int query(int pos) {
  23. int res=0;
  24. for(int i=pos;i;i-=low(i))
  25. res+=c[i];
  26. return res;
  27. }
  28. }T[145];
  29. void check(int i,int l,int r) {
  30. if(v[i]<v[l])ans--;
  31. if(v[i]>v[l])ans++;
  32. if(v[i]<v[r])ans++;
  33. if(v[i]>v[r])ans--;
  34. }
  35. int main() {
  36. n=read(),block=sqrt(n);
  37. for(int i=1;i<=n;i++) {
  38. v[i]=tmp[i]=read(),bel[i]=(i-1)/block+1;
  39. if(bel[i]!=bel[i-1])R[bel[i-1]]=i-1,L[bel[i]]=i;
  40. }R[bel[n]]=n;
  41. sort(tmp+1,tmp+n+1);
  42. cnt=unique(tmp+1,tmp+n+1)-tmp-1;
  43. for(int i=1;i<=n;i++)
  44. v[i]=lower_bound(tmp+1,tmp+cnt+1,v[i])-tmp;
  45. for(int i=n;i;i--) {
  46. ans+=T[0].query(v[i]-1);
  47. T[0].add(v[i],1);
  48. T[bel[i]].add(v[i],1);
  49. }
  50. printf("%d\n",ans);
  51. m=read();
  52. while(m--) {
  53. int l=read(),r=read();
  54. if(r<l)swap(l,r);
  55. if(bel[l]==bel[r]) {
  56. for(int i=l+1;i<r;i++)
  57. check(i,l,r);
  58. }
  59. else {
  60. for(int i=l+1;i<=R[bel[l]];i++)
  61. check(i,l,r);
  62. for(int i=L[bel[r]];i<r;i++)
  63. check(i,l,r);
  64. for(int i=bel[l]+1;i<bel[r];i++) {
  65. ans-=T[i].query(v[l]-1);
  66. ans+=T[i].query(cnt)-T[i].query(v[l]);
  67. ans+=T[i].query(v[r]-1);
  68. ans-=T[i].query(cnt)-T[i].query(v[r]);
  69. }
  70. T[bel[l]].add(v[l],-1),T[bel[l]].add(v[r],1);
  71. T[bel[r]].add(v[l],1),T[bel[r]].add(v[r],-1);
  72. }
  73. if(v[l]>v[r])ans--;
  74. if(v[l]<v[r])ans++;
  75. swap(v[l],v[r]);
  76. printf("%d\n",ans);
  77. }
  78. return 0;
  79. }

BZOJ2141:排队的更多相关文章

  1. BZOJ2141 排队 树状数组 分块

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2141.html 题目传送门 - BZOJ2141 题意 给定一个序列 $a$ ,先输出原先的逆序对数. ...

  2. bzoj2141排队(辣鸡但是好写的方法)

    题意很明确,也非常经典: 一个支持查询 区间中比k大的数的个数 并且支持单点修改的序列 ——因为题意可以转化为:查询这两个数中比后者大的个数.比后者小的个数.比前者大的个数.比前者小的个数(根据这4个 ...

  3. BZOJ2141: 排队

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2141 分块加树状数组. 离散化之后,每一个块建一个树状数组.交换x,y,与x左边的数和y右 ...

  4. bzoj2141排队

    /* 动态求逆序对,可以树套树来写, 将交换操作理解成插入和删除比较好理解, 里层是个区间求和的线段树就好了 或者叫 带修主席树? */ #include<cstdio> #include ...

  5. BZOJ2141排队——树状数组套权值线段树(带修改的主席树)

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...

  6. bzoj2141: 排队(分块+树状数组)

    块套树为什么会这么快.. 先跑出原序列逆序对. 显然交换两个位置$l,r$,对$[1,l),(r,n]$里的数没有影响,所以只需要考虑$[l,r]$内的数. 设$(l,r)$内的数$a_i$,则按以下 ...

  7. BZOJ2141:排队(分块,树状数组)

    Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们 ...

  8. 【分块】【树套树】bzoj2141 排队

    考虑暴力更新的情况,设swap的是L,R位置的数.swap之后的逆序对数应该等于:之前的逆序对数+[L+1,R-1]中比 L位置的数 大的数的个数-[L+1,R-1]中比 L位置的数 小的数的个数-[ ...

  9. [bzoj2141][排队] (分块大法好)

    Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的 ...

  10. 树套树Day1线段树套平衡树bzoj3196

    您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...

随机推荐

  1. JSON.parse和JSON.stringify的作用

    //JSON.parse将字符串格式json转化为json对象 var str='{"name":"lingling","age":&quo ...

  2. CSS3 3D旋转下拉菜单

    在线演示 本地下载

  3. 二、linux题型

    1.[root@pyrene ~]# 这里root是当前登录用户  @分割     pyrene是主机名    -:表示当前登录环境   #:表示管理员 2.在/data下面创建一个文件oldboy. ...

  4. Android修改init.rc和init.xx.rc文件【转】

    本文转载自:https://blog.csdn.net/u013686019/article/details/47981249 一.文件简介 init.rc:Android在启动过程中读取的启动脚本文 ...

  5. windows环境下安装部署并启用zkui的web图形界面

    在此之前的工作:不是本机部署的三个服务器最为伪集群的zookeeper环境,并将三个为服务启动起来. 然后才有了下面的工作. 1. 首先,zkui项目地址:https://github.com/Dee ...

  6. 查看git安装目录

    有时候需要知道Git在电脑中的安装位置,这里简单介绍下: Mac平台:在命令行中输入which git, 就会显示git的安装位置了; Windows平台:打开cmd,输入where git就会显示g ...

  7. RHCE学习笔记 管理1 (第一、二章)

    第一章 命令行访问 1.Ctrl+alt+F2~F6 切到虚拟控制台,ctrl+alt+F1 回到图形界面 2.格式 : 命令 选项 参数 [] 为可选项目            ...表示该项目任意 ...

  8. mysql里的ibdata1文件

    mysql大多数磁盘空间被 InnoDB 的共享表空间 ibdata1 使用.而你已经启用了 innodb_file_per_table,所以问题是: ibdata1存了什么? 当你启用了innodb ...

  9. eclipse修改端口启动多个tomcat

    参考:https://blog.csdn.net/zl544434558/article/details/47857343 在一个eclipse启动多个tomcat,修改tomcat的端口是不可以的, ...

  10. Tensorflow 从零开始

    1.安装pip pip是一个用于管理和安装Python包的工具,类似于LINUX 的yum命令一样! 命令(Ubuntu系统):sudo apt-get install python-pip 验证安装 ...