luogu1975 排队(分块)

给你一个长度为n的序列,每次交换给定的两个数,输出每次操作后的逆序对个数。

首先考虑求出刚开始的逆序对。接着相当于带修改的求区间中比x大的数。

可以用分块,每个块内排序,然后维护排序后的块。每次查询,块外二分,块内暴力。

  1. #include <cmath>
  2. #include <cstdio>
  3. #include <algorithm>
  4. using namespace std;
  5. const int maxn=2e4+5, maxbar=2e2+5;
  6. int n, a[maxn], b[maxn], ans;
  7. int m, barlen, bel[maxn], cntbar;
  8. struct node{
  9. int id, v;
  10. }sted[maxn], t;
  11. bool cmp(const node &a, const node &b){ return a.v<b.v; }
  12. int tmp[maxn];
  13. void msort(int l, int r){ //[l, r)
  14. if (l==r-1) return;
  15. int mid=(l+r)>>1;
  16. msort(l, mid); msort(mid, r);
  17. int i=l, j=mid, cnt=0;
  18. while (i<mid&&j<r){
  19. if (b[i]<=b[j]) tmp[cnt++]=b[i++], ans+=j-mid;
  20. else tmp[cnt++]=b[j++];
  21. }
  22. while (i<mid) tmp[cnt++]=b[i++], ans+=j-mid;
  23. while (j<r) tmp[cnt++]=b[j++];
  24. for (int i=0; i<cnt; ++i) b[l+i]=tmp[i];
  25. }
  26. //在[l, r)中大于x的数有几个
  27. int bigger(int l, int r, int x){
  28. if (l>=r) return 0;
  29. int cnt=0; int bl=bel[l]+1, br=bel[r-1]-1;
  30. if (bel[l]==bel[r-1]){
  31. for (int i=l; i<r; ++i) if (a[i]>x) ++cnt;
  32. return cnt;
  33. }
  34. t.v=x;
  35. for (int i=bl; i<=br; ++i)
  36. cnt-=upper_bound(sted+i*barlen, sted+(i+1)*barlen, t, cmp)
  37. -(sted+(i+1)*barlen);
  38. for (int i=l; i==l||bel[i]==bel[i-1]; ++i)
  39. if (a[i]>x) ++cnt;
  40. for (int i=r-1; i==r-1||bel[i]==bel[i+1]; --i)
  41. if (a[i]>x) ++cnt;
  42. return cnt;
  43. }
  44. //在[l, r)中小于x的数有几个
  45. int smaller(int l, int r, int x){
  46. if (l>=r) return 0;
  47. int cnt=0; int bl=bel[l]+1, br=bel[r-1]-1;
  48. if (bel[l]==bel[r-1]){
  49. for (int i=l; i<r; ++i) if (a[i]<x) ++cnt;
  50. return cnt;
  51. }
  52. t.v=x;
  53. for (int i=bl; i<=br; ++i)
  54. cnt+=lower_bound(sted+i*barlen, sted+(i+1)*barlen, t, cmp)
  55. -(sted+i*barlen);
  56. for (int i=l; i==l||bel[i]==bel[i-1]; ++i)
  57. if (a[i]<x) ++cnt;
  58. for (int i=r-1; i==r-1||bel[i]==bel[i+1]; --i)
  59. if (a[i]<x) ++cnt;
  60. return cnt;
  61. }
  62. //维护sorted数组
  63. int change(int pos, int num){
  64. for (int i=bel[pos]*barlen; i<(bel[pos]+1)*barlen; ++i)
  65. if (sted[i].id==pos){ pos=i; break; }
  66. sted[pos].v=num;
  67. while (sted[pos].v>sted[pos+1].v&&bel[pos]==bel[pos+1])
  68. swap(sted[pos], sted[pos+1]), ++pos;
  69. while (sted[pos].v<sted[pos-1].v&&bel[pos]==bel[pos-1])
  70. swap(sted[pos], sted[pos-1]), --pos;
  71. return pos;
  72. }
  73. void modify(int pos, int num){
  74. ans-=bigger(0, pos, a[pos]);
  75. ans-=smaller(pos, n, a[pos]);
  76. a[pos]=num; change(pos, num);
  77. ans+=bigger(0, pos, num);
  78. ans+=smaller(pos, n, num);
  79. }
  80. int main(){
  81. scanf("%d", &n); barlen=sqrt(n);
  82. for (int i=0; i<n; ++i){
  83. scanf("%d", &a[i]);
  84. b[i]=sted[i].v=a[i]; sted[i].id=i;
  85. }
  86. msort(0, n); printf("%d\n", ans);
  87. for (int i=0; i<n; ++i) bel[i]=i/barlen; cntbar=bel[n-1]+1;
  88. for (int i=0; i<cntbar; ++i) \
  89. sort(sted+i*barlen, sted+min((i+1)*barlen, n), cmp);
  90. scanf("%d", &m); int x, y, tmp;
  91. for (int i=0; i<m; ++i){
  92. scanf("%d%d", &x, &y); --x; --y; tmp=a[x];
  93. modify(x, a[y]); modify(y, tmp);
  94. //for (int j=0; j<n; ++j) printf("%d ", sted[j].v);
  95. //puts("");
  96. printf("%d\n", ans);
  97. }
  98. return 0;
  99. }

luogu1975 排队(分块)的更多相关文章

  1. Bzoj 2141: 排队 分块,逆序对,树状数组

    2141: 排队 Time Limit: 4 Sec  Memory Limit: 259 MBSubmit: 1310  Solved: 517[Submit][Status][Discuss] D ...

  2. bzoj 2141 : 排队 分块

    题目链接 2141: 排队 Time Limit: 4 Sec  Memory Limit: 259 MBSubmit: 1169  Solved: 465[Submit][Status][Discu ...

  3. bzoj 1699: [Usaco2007 Jan]Balanced Lineup排队 分块

    1699: [Usaco2007 Jan]Balanced Lineup排队 Time Limit: 5 Sec  Memory Limit: 64 MB Description 每天,农夫 John ...

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

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

  5. 【bzoj2141】排队 分块+树状数组

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

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

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

  7. BZOJ_2141_排队_树状数组+分块

    BZOJ2141_排队_树状数组+分块 Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了 ...

  8. 【BZOJ2141】排队 树状数组+分块

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

  9. Luogu-1975 [国家集训队]排队

    Luogu-1975 [国家集训队]排队 题面 Luogu-1975 题解 题意:给出一个长度为n的数列以及m个交换两个数的操作,问每次操作后逆序对数量 时间,下标和数的大小三维偏序,,,把交换操作看 ...

随机推荐

  1. BEC listen and translation exercise 44

    But over the past 70 years or so, there's been a massive increase in one type of crime which was wha ...

  2. linux命令学习笔记(38):cal 命令

    cal命令可以用来显示公历(阳历)日历.公历是现在国际通用的历法,又称格列历,通称阳历. “阳历”又名“太阳历”,系以地球绕行太阳一周为一年,为西方各国所通用,故又名“西历”. .命令格式: cal ...

  3. 重写ScrollView实现两个ScrollView的同步滚动显示

    1.背景介绍 最近项目用到两个ScrollView的同步显示,即拖动左边的ScrollView滚动的同时,实现右边的ScrollView同步滚动.此种情形常用在复杂界面布局中,比如左边的ScrollV ...

  4. 把自定义的decoder加入ffmpeg源码

    第一步: 在libavcodec目录下新建mkdecoder.c,并加入一下代码: /* *实现一个自己的decoder,编码工作其实就是把pkt的数据拷贝到frame *作者:缪国凯(MK) *82 ...

  5. cmd cvf war包

    1.进入要打包的目录下 --> cmd d: cd \路径 jar -cvf 包名.war * 2.解压 进入需要解压的目录 cd /depa123/webapps/css jar -xvf / ...

  6. 汇编题目:在屏幕中间显示a-z的所有字母,按ESC键改变字符颜色

    在屏幕中显示a-z字母,按ESC键改变字符颜色. ;程序功能:在屏幕中间同一点显示a-z的所有字符 ; 1.使用cpu循环空运行实现延迟 ; 2.按ESC键改变正在循环显示的字符的颜色 ; 3.程序完 ...

  7. JUI web企业应用框架 http://jui.org/

    官方网址: http://jui.org/ 这是一个很好的开发控件

  8. NB-IoT知识

    通常,我们把物联网设备分为三类: ①无需移动性,大数据量(上行),需较宽频段,比如城市监控摄像头. ②移动性强,需执行频繁切换,小数据量,比如车队追踪管理. ③无需移动性,小数据量,对时延不敏感,比如 ...

  9. 使用py 和flask 实现的服务器系统目录浏览,日志文件实时显示到网页的功能

    看日志希望带有彩色,希望从浏览器上看到,不用连到机器上看. 浏览系统的文件夹,scan + 系统文件夹的层级名字当做url路由,可以深层次看到机器上任何层级的文件夹,实现系统文件夹浏览下载. 如果是点 ...

  10. javaScript之Array方法

    Array类型和其他语言一样,是数据的有序列表,但不同的是数组的每一项们可以保存任何类型的数据. 1.检测方法(确定某个对象是不是数组) (1)value instanceof Array (2)Ar ...