$ \color{#0066ff}{ 题目描述 }$

排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。

红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足i<j且hi>hj的(i,j)数量。

幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。

\(\color{#0066ff}{输入格式}\)

第一行为一个正整数n,表示小朋友的数量;

第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;

第三行为一个正整数m,表示交换操作的次数;

以下m行每行包含两个正整数ai和bi­,表示交换位置ai与位置bi的小朋友。

\(\color{#0066ff}{输出格式}\)

输出文件共m+1行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。

\(\color{#0066ff}{输入样例}\)

  1. 3
  2. 130 150 140
  3. 2
  4. 2 3
  5. 1 3

\(\color{#0066ff}{输出样例}\)

  1. 1
  2. 0
  3. 3

\(\color{#0066ff}{数据范围与提示}\)

【样例说明】

未进行任何操作时,(2,3)满足条件;

操作1结束后,序列为130 140 150,不存在满足i<j且hi>hj的(i,j)对;

操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。

对于15%的数据,\(n,m \le 15\);

对于30%的数据,\(n,m \le 200\);

在剩下的70%数据中:

存在15%的数据,\(h_i\)各不相同;

存在15%的数据,\(1^{10} \le h_i \le 1^{60}\);

以上两类数据不存在交集。

对于100%的数据,\(1 \le m \le 2\times 10^3\),\(1 \le n \le 2 \times 10^4\),\(1 \le h_i \le 10^9\),\(a_i \ne b_i\),\(1 \le a_i,b_i \le n\)。

\(\color{#0066ff}{题解}\)

一句话题意,给你一个序列,每次交换其中两个元素,每次输出逆序对数量

直接树套树, 每次减去改之前的贡献,然后修改,然后再加上改之后的贡献即可

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. LL read() {
  4. char ch; LL x = 0, f = 1;
  5. while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
  6. for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
  7. return x * f;
  8. }
  9. template<class T> bool chkmax(T &a, const T &b) { return a < b? a = b, 1 : 0; }
  10. template<class T> bool chkmin(T &a, const T &b) { return b < a? a = b, 1 : 0; }
  11. const int maxn = 1e5 + 10;
  12. struct Splay {
  13. protected:
  14. struct node {
  15. node *ch[2], *fa;
  16. int siz, val;
  17. node(int siz = 0, int val = 0): siz(siz), val(val) { ch[0] = ch[1] = fa = NULL; }
  18. bool isr() { return this == fa->ch[1]; }
  19. void upd() { siz = (ch[0]? ch[0]->siz : 0) + (ch[1]? ch[1]->siz : 0) + 1; }
  20. int rkmin() { return (ch[0]? ch[0]->siz + 1 : 1); }
  21. int rkmax() { return (ch[1]? ch[1]->siz + 1 : 1); }
  22. }*root;
  23. void rot(node *x) {
  24. node *y = x->fa, *z = y->fa;
  25. bool k = x->isr(); node *w = x->ch[!k];
  26. if(y != root) z->ch[y->isr()] = x;
  27. else root = x;
  28. (x->ch[!k] = y)->ch[k] = w;
  29. (y->fa = x)->fa = z;
  30. if(w) w->fa = y;
  31. y->upd(), x->upd();
  32. }
  33. void splay(node *o) {
  34. while(o != root) {
  35. if(o->fa != root) rot(o->isr() ^ o->fa->isr()? o : o->fa);
  36. rot(o);
  37. }
  38. }
  39. node *merge(node *fa, node *x, node *y) {
  40. if(x) x->fa = fa;
  41. if(y) y->fa = fa;
  42. if(!x || !y) return x? x : y;
  43. if(rand() & 1) return x->ch[1] = merge(x, x->ch[1], y), x->upd(), x;
  44. else return y->ch[0] = merge(y, x, y->ch[0]), y->upd(), y;
  45. }
  46. public:
  47. Splay() { root = NULL; }
  48. int querymin(int val) {
  49. int rank = 0; node *o = root;
  50. while(o) {
  51. if(o->val < val) rank += o->rkmin(), o = o->ch[1];
  52. else o = o->ch[0];
  53. }
  54. return rank;
  55. }
  56. int querymax(int val) {
  57. int rank = 0; node *o = root;
  58. while(o) {
  59. if(o->val > val) rank += o->rkmax(), o = o->ch[0];
  60. else o = o->ch[1];
  61. }
  62. return rank;
  63. }
  64. void ins(int val) {
  65. if(!root) return (void)(root = new node(1, val));
  66. node *o = root, *fa = NULL;
  67. while(o) fa = o, o = o->ch[val > o->val];
  68. fa->ch[val > fa->val] = o = new node(1, val);
  69. o->fa = fa, splay(o);
  70. }
  71. void del(int val) {
  72. node *o = root;
  73. while(o->val != val) o = o->ch[val > o->val];
  74. splay(o);
  75. root = merge(NULL, o->ch[0], o->ch[1]);
  76. }
  77. };
  78. struct Tree {
  79. protected:
  80. struct node {
  81. node *ch[2];
  82. int l, r;
  83. Splay T;
  84. node(int l = 0, int r = 0): l(l), r(r) { ch[0] = ch[1] = NULL; }
  85. int mid() { return (l + r) >> 1; }
  86. }*root;
  87. void build(node *&o, int l, int r, int *a) {
  88. o = new node(l, r);
  89. for(int i = l; i <= r; i++) o->T.ins(a[i]);
  90. if(l == r) return;
  91. build(o->ch[0], l, o->mid(), a);
  92. build(o->ch[1], o->mid() + 1, r, a);
  93. }
  94. int querymin(node *o, int l, int r, int val) {
  95. if(l > r) return 0;
  96. if(l <= o->l && o->r <= r) return o->T.querymin(val);
  97. int ans = 0;
  98. if(l <= o->mid()) ans += querymin(o->ch[0], l, r, val);
  99. if(r > o->mid()) ans += querymin(o->ch[1], l, r, val);
  100. return ans;
  101. }
  102. int querymax(node *o, int l, int r, int val) {
  103. if(l > r) return 0;
  104. if(l <= o->l && o->r <= r) return o->T.querymax(val);
  105. int ans = 0;
  106. if(l <= o->mid()) ans += querymax(o->ch[0], l, r, val);
  107. if(r > o->mid()) ans += querymax(o->ch[1], l, r, val);
  108. return ans;
  109. }
  110. public:
  111. void init(int n, int *a) { build(root, 1, n, a); }
  112. void change(int pos, int old, int now) {
  113. node *o = root;
  114. while(1) {
  115. o->T.del(old), o->T.ins(now);
  116. if(o->l == o->r) break;
  117. if(pos <= o->mid()) o = o->ch[0];
  118. else o = o->ch[1];
  119. }
  120. }
  121. int querymin(int l, int r, int val) { return querymin(root, l, r, val); }
  122. int querymax(int l, int r, int val) { return querymax(root, l, r, val); }
  123. }T;
  124. int val[maxn], n;
  125. int main() {
  126. n = read();
  127. for(int i = 1; i <= n; i++) val[i] = read();
  128. T.init(n, val);
  129. int ans = 0;
  130. for(int i = 1; i <= n; i++) ans += T.querymax(1, i - 1, val[i]) + T.querymin(i + 1, n, val[i]);
  131. printf("%d\n", ans >>= 1);
  132. for(int Q = read(); Q --> 0;) {
  133. int x = read(), y = read();
  134. ans -= T.querymax(1, x - 1, val[x]) + T.querymin(x + 1, n, val[x]);
  135. T.change(x, val[x], val[y]);
  136. ans += T.querymax(1, x - 1, val[y]) + T.querymin(x + 1, n, val[y]);
  137. ans -= T.querymax(1, y - 1, val[y]) + T.querymin(y + 1, n, val[y]);
  138. T.change(y, val[y], val[x]);
  139. ans += T.querymax(1, y - 1, val[x]) + T.querymin(y + 1, n, val[x]);
  140. std::swap(val[x], val[y]);
  141. printf("%d\n", ans);
  142. }
  143. return 0;
  144. }

P1975 [国家集训队]排队 线段树套平衡树维护动态逆序对查询的更多相关文章

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

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

  2. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2271  Solved: 935[Submit][Stat ...

  3. CF 19D - Points 线段树套平衡树

    题目在这: 给出三种操作: 1.增加点(x,y) 2.删除点(x,y) 3.询问在点(x,y)右上方的点,如果有相同,输出最左边的,如果还有相同,输出最低的那个点 分析: 线段树套平衡树. 我们先离散 ...

  4. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  5. P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)

    P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...

  6. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  7. bzoj 2120 线段树套平衡树

    先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心..... 首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有, 但是能给我们一 ...

  8. [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)

    题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...

  9. P3380 【模板】二逼平衡树(树套树) 线段树套平衡树

    \(\color{#0066ff}{ 题目描述 }\) 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上 ...

随机推荐

  1. Struts2分模块开发

    -------------------siwuxie095 Struts2 分模块开发 在实际开发中,如果一个项目是团队开发的,也就是很多人开发的, 每个人都需要去修改 struts.xml,因为 s ...

  2. RGB直方图与UV直方图

    ------------------------------------------------------------------------------------ from skimage im ...

  3. sourcetree免注册方法

    step1: https://www.sourcetreeapp.com/官网下载windows版软件 step2: 右键-->以管理员身份运行,便安装成功了 step3: 安装好之后会有这么一 ...

  4. 修改字符集AL32UTF8修改为ZHS16GBK详解

    登陆sqlplus,在命令行输入 sqlplus sys/sys as sysdba;//登陆sqlplus SQL>SHUTDOWN IMMEDIATE; SQL>STARTUP MOU ...

  5. RTX二次开发::检索 COM 类工厂中 CLSID 为 {79210E58-99EB-45D0-8890-763EFEAA143F} 的组件失败,

    解决方法: 1.Interop.RTXSAPILib.dll这个是32位的 将IIS 应用程序池 启用32位应用程序 设置为true就可以了, 2.把编译好的程序选择X86平台运行,就好了 程序员的基 ...

  6. 线上服务内存OOM问题定位

    转自:架构师之路,http://mp.weixin.qq.com/s/iOC1fiKDItn3QY5abWIelg 相信大家都有感触,线上服务内存OOM的问题,是最难定位的问题,不过归根结底,最常见的 ...

  7. vim全局替换命令-乾颐堂

    语法为 :[addr]s/源字符串/目的字符串/[option] 全局替换命令为::%s/源字符串/目的字符串/g [addr] 表示检索范围,省略时表示当前行. 如:“1,20” :表示从第1行到2 ...

  8. C#中把任意类型的泛型集合转换成SQLXML数据格式的小例子

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  9. css实现二级菜单显示和收缩

    <ul class="nav"> <li><a href="#">一级菜单</a> <ul class=& ...

  10. C/C++语言中指针数组和数组指针比较区别

    指针数组:int *p[3] 定义一个指针数组,其中每个数组元素指向一个int型变量的地址 意思就是指针的数组,数组里面都是指针 例子: int *p[3];//定义了一个指针数组,有3个成员,每个成 ...