4053

思路:

主席树

先分别求前缀和后缀的逆序数

然后要求某一段的逆序数,就可以根据前缀或着后缀根据容斥求出答案,

这样需要枚举这一段中的数,求之前或者之后有多少个比他大或比他小的数,

这个可以通过用主席数维护权值线段树来做

然后每次枚举断开后小的那段区间,这样最多需要枚举n*log(n)次

复杂度:n*log(n)*log(n)

代码:

  1. #pragma GCC optimize(2)
  2. #pragma GCC optimize(3)
  3. #pragma GCC optimize(4)
  4. #include<bits/stdc++.h>
  5. using namespace std;
  6. #define fi first
  7. #define se second
  8. #define pi acos(-1.0)
  9. #define LL long long
  10. //#define mp make_pair
  11. #define pb push_back
  12. #define ls rt<<1, l, m
  13. #define rs rt<<1|1, m+1, r
  14. #define ULL unsigned LL
  15. #define pll pair<LL, LL>
  16. #define pii pair<int, int>
  17. #define piii pair<pii, int>
  18. #define mem(a, b) memset(a, b, sizeof(a))
  19. #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  20. #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
  21. //head
  22.  
  23. const int N = 1e5 + , M = 2e6 + ;
  24. int a[N], p[N], root[N], bit[N], lson[M], rson[M], value[M], tot = , n;
  25. LL tmp[N], ans[N], pre[N], suf[N];
  26. multiset<LL> s;
  27. void build(int &x, int l, int r) {
  28. x = ++tot;
  29. if(l == r) {
  30. value[x] = ;
  31. return ;
  32. }
  33. int m = l+r >> ;
  34. build(lson[x], l, m);
  35. build(rson[x], m+, r);
  36. value[x] = value[lson[x]] + value[rson[x]];
  37. }
  38. void update(int old, int &x, int p, int v, int l, int r) {
  39. x = ++tot;
  40. lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v;
  41. if(l == r) return ;
  42. int m = l+r >> ;
  43. if(p <= m) update(lson[x], lson[x], p, v, l, m);
  44. else update(rson[x], rson[x], p, v, m+, r);
  45. }
  46. int query(int L, int R, int x, int l, int r) {
  47. if(L > R) return ;
  48. if(L <= l && r <= R) return value[x];
  49. int m = l+r >> , ans = ;
  50. if(L <= m) ans += query(L, R, lson[x], l, m);
  51. if(R > m) ans += query(L, R, rson[x], m+, r);
  52. return ans;
  53. }
  54. void add(int x, int v) {
  55. while(x <= n+) bit[x] += v, x += x&-x;
  56. }
  57. int sum(int x) {
  58. int ans = ;
  59. while(x) ans += bit[x], x -= x&-x;
  60. return ans;
  61. }
  62. int Find_pre(int pos) {
  63. int l = , r = pos, m = l+r >> ;
  64. while(l < r) {
  65. if(sum(pos) - sum(m-) > ) l = m + ;
  66. else r = m;
  67. m = l+r >> ;
  68. }
  69. return m;
  70. }
  71. int Find_nxt(int pos) {
  72. int l = pos, r = n, m = l+r+ >> ;
  73. while(l < r) {
  74. if(sum(m) - sum(pos-) > ) r = m - ;
  75. else l = m;
  76. m = l+r+ >> ;
  77. }
  78. return m;
  79. }
  80. void solve(int l, int m, int r) {
  81. if(l == r) return ;
  82. else if(l + == r) {
  83. if(l == m) tmp[l] = , s.insert();
  84. else tmp[l-] = , s.insert();
  85. }
  86. else {
  87. if(l == m) {
  88. LL t = tmp[l-];
  89. t -= (query(, a[m]-, root[r], , n) - query(, a[m]-, root[l], , n));
  90. tmp[l] = t;
  91. s.insert(t);
  92. }
  93. else if(r == m) {
  94. LL t = tmp[l-] - (query(a[m]+, n, root[r-], , n) - query(a[m]+, n, root[l-], , n));
  95. tmp[l-] = t;
  96. s.insert(t);
  97. }
  98. else {
  99. LL t = tmp[l-], t1, t2;
  100. if(m-l+ < r-m) {
  101. t1 = pre[m-] - pre[l-];
  102. for (int i = l; i < m; i++) {
  103. t1 -= query(a[i]+, n, root[l-], , n);
  104. }
  105.  
  106. t2 = t - t1;
  107. for (int i = l; i < m; i++) {
  108. t2 -= query(, a[i]-, root[r], , n) - query(, a[i]-, root[m-], , n);
  109. }
  110. t2 -= query(, a[m]-, root[r], , n) - query(, a[m]-, root[m], , n);
  111. }
  112. else {
  113. t2 = suf[m+] - suf[r+];
  114. for (int i = m+; i <= r; i++) {
  115. if(r+ <= n) t2 -= query(, a[i]-, root[n], , n) - query(, a[i]-, root[r], , n);
  116. }
  117.  
  118. t1 = t - t2;
  119. for (int i = m+; i <= r; i++) {
  120. t1 -= query(a[i]+, n, root[m], , n) - query(a[i]+, n, root[l-], , n);
  121. }
  122. t1 -= query(a[m]+, n, root[m-], , n) - query(a[m]+, n, root[l-], , n);
  123. }
  124. tmp[l-] = t1;
  125. tmp[m] = t2;
  126. s.insert(t1);
  127. s.insert(t2);
  128. }
  129. }
  130.  
  131. }
  132. int main() {
  133. int T;
  134. scanf("%d", &T);
  135. while(T--) {
  136. scanf("%d", &n);
  137. for (int i = ; i <= n; i++) scanf("%d", &a[i]);
  138. for (int i = ; i <= n; i++) scanf("%d", &p[i]);
  139. pre[] = suf[n+] = ;
  140. s.clear();
  141. tot = ;
  142. build(root[], , n);
  143. for (int i = ; i <= n; i++) update(root[i-], root[i], a[i], , , n);
  144. for (int i = n; i >= ; i--) {
  145. suf[i] = suf[i+] + query(, a[i]-, root[n], , n) - query(, a[i]-, root[i], , n);
  146. }
  147. for (int i = ; i <= n; i++) {
  148. pre[i] = pre[i-] + query(a[i]+, n, root[i-], , n);
  149. }
  150. for (int i = ; i <= n+; i++) bit[i] = ;
  151. tmp[] = suf[];
  152. s.insert(tmp[]);
  153. for (int i = ; i <= n; i++) {
  154. ans[i] = *s.rbegin();
  155. int t = ans[i]^p[i];
  156. int l = Find_pre(t), r = Find_nxt(t);
  157. s.erase(s.find(tmp[l-]));
  158. solve(l, t, r);
  159. add(t, );
  160. }
  161. for (int i = ; i <= n; i++) printf("%lld%c", ans[i], " \n"[i==n]);
  162. }
  163. return ;
  164. }

ZOJ 4053 Couleur的更多相关文章

  1. Couleur(启发式 + 主席树)(终于补坑了)

    ZOJ Problem Set - 4053 Couleur Time Limit: 6 Seconds      Memory Limit: 131072 KB DreamGrid has an a ...

  2. ZOJ People Counting

    第十三届浙江省大学生程序设计竞赛 I 题, 一道模拟题. ZOJ  3944http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=394 ...

  3. ZOJ 3686 A Simple Tree Problem

    A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a rooted tree, each no ...

  4. ZOJ Problem Set - 1394 Polar Explorer

    这道题目还是简单的,但是自己WA了好几次,总结下: 1.对输入的总结,加上上次ZOJ Problem Set - 1334 Basically Speaking ac代码及总结这道题目的总结 题目要求 ...

  5. ZOJ Problem Set - 1392 The Hardest Problem Ever

    放了一个长长的暑假,可能是这辈子最后一个这么长的暑假了吧,呵呵...今天来实验室了,先找了zoj上面简单的题目练练手直接贴代码了,不解释,就是一道简单的密文转换问题: #include <std ...

  6. ZOJ Problem Set - 1049 I Think I Need a Houseboat

    这道题目说白了是一道平面几何的数学问题,重在理解题目的意思: 题目说,弗雷德想买地盖房养老,但是土地每年会被密西西比河淹掉一部分,而且经调查是以半圆形的方式淹没的,每年淹没50平方英里,以初始水岸线为 ...

  7. ZOJ Problem Set - 1006 Do the Untwist

    今天在ZOJ上做了道很简单的题目是关于加密解密问题的,此题的关键点就在于求余的逆运算: 比如假设都是正整数 A=(B-C)%D 则 B - C = D*n + A 其中 A < D 移项 B = ...

  8. ZOJ Problem Set - 1001 A + B Problem

    ZOJ ACM题集,编译环境VC6.0 #include <stdio.h> int main() { int a,b; while(scanf("%d%d",& ...

  9. zoj 1788 Quad Trees

    zoj 1788 先输入初始化MAP ,然后要根据MAP 建立一个四分树,自下而上建立,先建立完整的一棵树,然后根据四个相邻的格 值相同则进行合并,(这又是递归的伟大),逐次向上递归 四分树建立完后, ...

随机推荐

  1. 本地win7ping VM linux ipv6地址问题

    前述 在windows和linux同时安装ipv6之后,系统将会自动分配一个link-local(链接本地)地址也就是ifconfig -a看到的一行[inet6 addr: fe80::20c:29 ...

  2. Oracle redo/undo 原理理解

    一. 什么是redo(用于重做数据) redo也就是重做日志文件(redo log file),Oracle维护着两类重做日志文件:在线(online)重做日志文件和归档(archived)重做日志文 ...

  3. svg动态添加小人

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  4. Codeforces 839C Journey - 树形动态规划 - 数学期望

    There are n cities and n - 1 roads in the Seven Kingdoms, each road connects two cities and we can r ...

  5. VC++ 获取exe或者dll版本信息

    #include <iostream> #include <atlstr.h> #pragma comment(lib,"version.lib") CSt ...

  6. python ---12 生成器 推导式

    一.生成器 函数中有yield 的就是生成器函数(替代了return) 本质就是迭代器   一个一个的创建对象     节省内存 1.创建生成器 最后以yield结束 1. 通过⽣成器函数   2. ...

  7. expr的字符串操作 表达式: length, index, match, substr等

    参考: http://www.linuxidc.com/Linux/2012-04/58095.htm expr的格式, 主要有两个, 一是 用expr option, 选项: 二是, expr的几个 ...

  8. Git 配置命令设置

    目录 查看配置文件路径: 查看其他配置命令: 修改配置文件默认路径: 查看配置文件路径: 查看系统级别配置: git config -e –-system D:/Program Files/Git/m ...

  9. LOJ#2444. 「NOI2011」阿狸的打字机

    题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B . P 两个字母. 经阿狸研究发现,这个打字机是 ...

  10. netty基础

    1,ServerBootstrap  [Bootstrap]