http://codeforces.com/contest/785/problem/E

一道经典的求逆序对的题目,可以用树状数组套平衡树解决

平衡树需要支持插入一个数,删除一个数,找比 x 小的数的个数和找比 x 大的数的个数便可以很好的维护逆序对个数

#include <bits/stdc++.h>
using namespace std; typedef unsigned long long ull;
typedef long long ll; template <typename T>
inline void read(T &f) {
f = 0; T fu = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') fu = -1; c = getchar();}
while(c >= '0' && c <= '9') {f = (f << 3) + (f << 1) + (c & 15); c = getchar();}
f *= fu;
} #define update(u) if(u -> left -> size) u -> size = u -> left -> size + u -> right -> size, u -> value = u -> right -> value
#define new_Node(a, b, c, d) (&(*st[cnt++] = Node(a, b, c, d)))
#define merge(a, b) new_Node(a -> size + b -> size, b -> value, a, b)
#define ratio 4 struct Node {
int size, value;
Node *left, *right;
Node (int a, int b, Node *c, Node *d) : size(a), value(b), left(c), right(d) {}
Node () {}
}*root[200005], *null, *st[8000005], t[8000005]; int a[200005];
ll ans = 0;
int n, m, cnt; void maintain(Node *u) {
if(u -> left -> size > u -> right -> size * ratio) u -> right = merge(u -> left -> right, u -> right), st[--cnt] = u -> left, u -> left = u -> left -> left;
if(u -> right -> size > u -> left -> size * ratio) u -> left = merge(u -> left, u -> right -> left), st[--cnt] = u -> right, u -> right = u -> right -> right;
} void ins(Node *u, int x) {
if(u -> size == 1) u -> left = new_Node(1, min(u -> value, x), null, null), u -> right = new_Node(1, max(u -> value, x), null, null);
else ins(x > u -> left -> value ? u -> right : u -> left, x);
update(u); maintain(u);
} void earse(Node *u, int x) {
if(u -> left -> size == 1 && u -> left -> value == x) st[--cnt] = u -> left, st[--cnt] = u -> right, *u = *u -> right;
else if(u -> right -> size == 1 && u -> right -> value == x) st[--cnt] = u -> left, st[--cnt] = u -> right, *u = *u -> left;
else earse(x > u -> left -> value ? u -> right : u -> left, x);
update(u); maintain(u);
} int find1(Node *u, int x) {
if(u -> size == 1) return x > u -> value;
return x > u -> left -> value ? find1(u -> right, x) + u -> left -> size : find1(u -> left, x);
} int find2(Node *u, int x) {
if(u -> size == 1) return x < u -> value;
return x < u -> left -> value ? find2(u -> left, x) + u -> right -> size : find2(u -> right, x);
} int lowbit(int x) {return x & -x;} int main() {
null = new Node(0, 0, 0, 0);
cin >> n >> m;
for(int i = 1; i <= n; i++) root[i] = new Node(1, INT_MAX, null, null);
for(int i = 0; i < 8000005; i++) st[i] = &t[i];
for(int t = 1; t <= n; t++) {
a[t] = t;
for(int i = t; i <= n; i += lowbit(i)) ins(root[i], t);
}
while(m--) {
int x, y; read(x); read(y);
if(x == y) {
printf("%I64d\n", ans);
continue;
}
for(int i = x; i; i -= lowbit(i)) ans -= (ll)find2(root[i], a[x]) - 1ll;
for(int i = n; i; i -= lowbit(i)) ans -= (ll)find1(root[i], a[x]);
for(int i = x - 1; i; i -= lowbit(i)) ans += (ll)find1(root[i], a[x]);
for(int i = x; i <= n; i += lowbit(i)) earse(root[i], a[x]);
for(int i = y; i; i -= lowbit(i)) ans -= (ll)find2(root[i], a[y]) - 1ll;
for(int i = n; i; i -= lowbit(i)) ans -= (ll)find1(root[i], a[y]);
for(int i = y - 1; i; i -= lowbit(i)) ans += (ll)find1(root[i], a[y]);
for(int i = y; i <= n; i += lowbit(i)) earse(root[i], a[y]);
swap(a[x], a[y]);
for(int i = x; i <= n; i += lowbit(i)) ins(root[i], a[x]);
for(int i = x; i; i -= lowbit(i)) ans += (ll)find2(root[i], a[x]) - 1ll;
for(int i = n; i; i -= lowbit(i)) ans += (ll)find1(root[i], a[x]);
for(int i = x - 1; i; i -= lowbit(i)) ans -= (ll)find1(root[i], a[x]);
for(int i = y; i <= n; i += lowbit(i)) ins(root[i], a[y]);
for(int i = y; i; i -= lowbit(i)) ans += (ll)find2(root[i], a[y]) - 1ll;
for(int i = n; i; i -= lowbit(i)) ans += (ll)find1(root[i], a[y]);
for(int i = y - 1; i; i -= lowbit(i)) ans -= (ll)find1(root[i], a[y]);
printf("%I64d\n", ans);
}
return 0;
}

codeforces785E的更多相关文章

  1. Codeforces785E - Anton and Permutation

    Portal Description 对一个长度为\(n(n\leq2\times10^5)\)的数列\(a\)进行\(m(m\leq5\times10^4)\)次操作,数列初始时为\(\{1,2,. ...

随机推荐

  1. java核心知识点----创建线程的第三种方式 Callable 和 Future CompletionService

    前面已经指出通过实现Runnable时,Thread类的作用就是将run()方法包装成线程执行体,那么是否可以直接把任意方法都包装成线程执行体呢?Java目前不行,但其模仿者C#中是可以的. Call ...

  2. 使用Windows绘图合成多张图

    [使用Windows绘图合成多张图] 1.点击图片右键选择打开方式→选择画图工具打开图片. 2.这时图片可以改变外框大小,将外框尽量弄大些. 3.点击编辑选中下拉菜单中的粘贴来源,选择需要增加进来的图 ...

  3. linux系统软件版本升级

    在安装完软件之后,在同一层目录生成一个符号链接,并把当前软件的目录映射到这个链接上,后面的操作都只通过这个链接去做,以后升级版本的时候,把最新的软件目录映射到这个链接上就可以了. 如我刚装的apach ...

  4. cannot launch node of type [arbotix_python/arbotix_driver]: arbotix_python

    这个时候提示错误: ERROR: cannot launch node of type [arbotix_python/arbotix_driver]: arbotix_python ROS path ...

  5. .net 多线程同步的相关知识点

    在多线程开发中,共享对象的同步是经常遇到的问题,以下总结了C#中线程同步的几种技术: 1,InterLocked原子操作 Decrement(ref int location);递减1 Add(ref ...

  6. 快速求出n!的质因数的个数

    一般做组合数的题目都要进行质因数的分解,我们一般是for循环对每个数进行质因数分解,大多数情况都不会超时,但极少数的情况下,题目会不允许这样的做法,所以我们需要学会一种更快的方法来求质因数. 我们一般 ...

  7. select下拉列表

    1.写 <!DOCTYPE html> <html> <head> <title></title> <script language= ...

  8. 两个线程并发执行以下代码,假设a是全局变量,那么以下输出______是不可能的?

    3.两个线程并发执行以下代码,假设a是全局变量,那么以下输出______是不可能的? void foo(){    ++a;    printf("%d ",a);}A.3 2   ...

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

    window.onload=function(){ var aLi=document.getElementsByTagName('li'); for(var i=0; i<aLi.length; ...

  10. 网络编程释疑之:单台服务器上的并发TCP连接数可以有多少

    曾几何时我们还在寻求网络编程中C10K问题的解决方案,但是现在从硬件和操作系统支持来看单台服务器支持上万并发连接已经没有多少挑战性了.我们先假设单台服务器最多只能支持万级并发连接,其实对绝大多数应用来 ...