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. Android——eclipse共享library以及导出jar包[转]

    目录(?)[-] 一apk之间共享Class 二apk导出jar包   android的apk在在eclipse上进行开发的时候,有时候需要import其它包中的一些class,正常的方法就是在jav ...

  2. centos6.5系统hadoop2.7安装sqoop

    一.sqoop简介 Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql.postgresql...)间进行数据的传递,可以将一个关系型数据库(例如 : MySQL ...

  3. sql查询exist替换in

    很多时候用 exists 代替 in 是一个好的选择: select num from a where num in(select num from b) 用下面的语句替换: select num f ...

  4. jedis的publish/subscribe[转]含有redis源码解析

    首先使用redis客户端来进行publish与subscribe的功能是否能够正常运行. 打开redis服务器 [root@localhost ~]# redis-server /opt/redis- ...

  5. Luogu 4705 玩游戏

    看见这个题依稀想起了$5$月月赛时候的事情,到现在仍然它感觉非常神仙. 游戏$k$次价值的期望答案 $$ans_k = \frac{1}{nm}\sum_{i = 1}^{n}\sum_{j = 1} ...

  6. 洛谷 P3659 [USACO17FEB]Why Did the Cow Cross the Road I G

    //神题目(题目一开始就理解错了)... 题目描述 Why did the cow cross the road? Well, one reason is that Farmer John's far ...

  7. Red Hat 6.5 Samba服务器的搭建(匿名访问,免登录)

    搭建Samba服务器是为了实现Linux共享目录之后,在Windows可以直接访问该共享目录. 现在介绍如何在红帽6.5系统中搭建Samba服务. 搭建Samba服务之前,yum源必须配置好,本地源和 ...

  8. Spring.net页面属性注入

    .条件spring.web程序集 1.1 system.web配置 <httpHandlers> <add verb="*" path="*.aspx& ...

  9. 基于Xcode5的本地化

    一.程序名国际化   1.首先添加应用对多语言支持的国际化文件   点击工程根目录,然后选择PROJECT下的项目,然后选择Info选项卡,在底部可以看到Localizations,点击“+”号,可以 ...

  10. Python 抓取html所有特定元素的方法

    直接上代码哦,够直接了吧~ from lxml import etree #import mechanize import lxml.html #import cookielib #br = mech ...