【LG1393】动态逆序对

题面

洛谷

题解

\(CDQ\)分治,按照时间来分治

应为一个删除不能对前面的操作贡献,所以考虑一个删除操作对它后面时间的操作的贡献

用上一个答案减去次贡献即可

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
namespace IO {
const int BUFSIZE = 1 << 20;
char ibuf[BUFSIZE], *is = ibuf, *it = ibuf;
inline char gc() {
if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin);
return *is++;
}
}
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc();
if (ch == '-') w = -1 , ch = IO::gc();
while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc();
return w * data;
}
const int MAX_N = 40005;
struct Node { int x, y, z, s; } t[MAX_N];
bool cmp_x(Node a, Node b) { return a.x < b.x; }
bool cmp_y(Node a, Node b) { return a.y < b.y; }
int N, M, ans, X[MAX_N], a[MAX_N], b[MAX_N], c[MAX_N], d[MAX_N];
inline int lb(int x) { return x & -x; }
void add(int x, int v) { while (x <= N) c[x] += v, x += lb(x); }
int sum(int x) { int res = 0; while (x > 0) res += c[x], x -= lb(x); return res; }
void Div(int l, int r) {
if (l == r) return ;
int mid = (l + r) >> 1;
Div(l, mid); Div(mid + 1, r);
int j = mid + 1;
for (int i = l; i <= mid; i++) {
for ( ; j <= r && t[j].y < t[i].y; ) add(t[j].z, 1), ++j;
t[i].s += sum(N) - sum(t[i].z);
}
for (int i = mid + 1; i < j; i++) add(t[i].z, -1);
j = r;
for (int i = mid; i >= l; i--) {
for ( ; j > mid && t[j].y > t[i].y; ) add(t[j].z, 1), --j;
t[i].s += sum(t[i].z - 1);
}
for (int i = r; i > j; i--) add(t[i].z, -1);
inplace_merge(&t[l], &t[mid + 1], &t[r + 1], cmp_y);
}
int main () {
N = gi(), M = gi();
for (int i = 1; i <= N; i++) X[i] = a[i] = gi();
sort(&X[1], &X[N + 1]);
for (int i = 1; i <= N; i++) a[i] = lower_bound(&X[1], &X[N + 1], a[i]) - X;
for (int i = N; i >= 1; i--) ans += sum(a[i] - 1), add(a[i], 1);
for (int i = 1; i <= N; i++) t[i].x = N + 1, t[i].y = i, t[i].z = a[i];
for (int i = 1; i <= M; i++) {
d[i] = gi();
t[d[i]].x = i;
}
sort(&t[1], &t[N + 1], cmp_x);
memset(c, 0, sizeof(c));
Div(1, N);
for (int i = 1; i <= N; i++) c[t[i].y] = t[i].s;
printf("%d ", ans);
for (int i = 1; i <= M; i++) printf("%d ", ans -= c[d[i]]);
return 0;
}

最新文章

  1. System.Linq.Dynamic的使用
  2. archlinux 打印机驱动安装
  3. ndk学习7: 使用静态库
  4. Python - 异步IO\数据库\队列\缓存
  5. HDU 4310 贪心
  6. Android:储存方式之SharePreferences
  7. HashMap使用
  8. POJ1329题
  9. SharePoint解决方案由VS2010升级到VS2013部署页面报错
  10. svn密码问题
  11. ELK搭建指南(linux及Windows)
  12. ##2.基础服务(SQl,RabbitMQ)-- openstack pike
  13. 使用XStream是实现XML与Java对象的转换(5)--Object Stream
  14. drf 单表
  15. 没有与这些操作数匹配的 &quot;&lt;&lt;&quot; 运算符 操作数类型为: std::ostream &lt;&lt; std::string
  16. wsgiref源码解析
  17. (转载)关于usr/bin/ld: cannot find -lxxx问题总结
  18. monkey测试基础
  19. Struts2(五)数据校验
  20. wsdl 结构解析

热门文章

  1. No module named _sqlite3
  2. vim使用常看
  3. non-fragile:oc2.0特性
  4. HDU 2897 邂逅明下 ( bash 博弈变形
  5. ARM 汇编指令集 特点之一:条件执行后缀
  6. OpenID Connect Core 1.0(二)ID Token
  7. Oracle 体系结构四 逻辑和物理存储结构之间的关系
  8. Web—02-轻松理解css
  9.  linux命令sed与awk是干什么用的,怎么用?
  10. java 整型数据转换为小数类型 BigDecimal 装换为Double