codeforces785E
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的更多相关文章
- Codeforces785E - Anton and Permutation
Portal Description 对一个长度为\(n(n\leq2\times10^5)\)的数列\(a\)进行\(m(m\leq5\times10^4)\)次操作,数列初始时为\(\{1,2,. ...
随机推荐
- swarmkit
SwarmKit是用于在任何规模上编排分布式系统的工具包. 它包括节点发现的原语,基于raft的共识,任务调度等. 其主要优点是: 分布式:SwarmKit使用raft共识算法来协调,不依赖单一故障点 ...
- 字符图元 & 显示列表
[字符图元] 1.typeface(字样),即设计风格,如Courier等. 2.font(字体),如10磅Courier斜体. 3.monspace即为等宽字体,proportional为非等宽字体 ...
- 详细探究Spark的shuffle实现
Background 在MapReduce框架中,shuffle是连接Map和Reduce之间的桥梁,Map的输出要用到Reduce中必须经过shuffle这个环 节,shuffle的性能高低直接影响 ...
- 解剖Nginx·模块开发篇(5)解读内置非默认模块 ngx_http_stub_status_module
1 Background ngx_http_stub_status_module 是一个 Nginx 的内置 HTTP 模块,该模块可以提供 Nginx 的状态信息.默认情况下这个模块是不被编译进来的 ...
- Openssl pkeyutl命令
一.简介 pkeyutl命令能够测试所支持的密钥算法的性能 二.语法 openssl rsautl [-in file] [-out file] [-sigfile file] [-inkey fil ...
- vim调用替换文件内容
:s/vivian/sky/ 替换当前行第一个 vivian 为 sky :s/vivian/sky/g 替换当前行所有 vivian 为 sky :n,$s/vivian/sky/ 替换 ...
- gitlab centos 安装配置运维笔记
写在前面 如果你需要一个git服务器,为企业或自己的团队托管代码而又不希望将代码仓库存储到第三方.你可以在自己的服务器上搭建一个gitlab. 本文为我在最初安装配置gitlab服务器的时候留存的笔记 ...
- vmware workstation 12 密钥
VMware Workstation 12序列号:5A02H-AU243-TZJ49-GTC7K-3C61N
- 白盒测试实践-任务进度-Day01
12-05 任务安排 小组成员 华同学.郭同学.覃同学.刘同学.穆同学.沈同学 任务划分 任务1:依据白盒测试方法设计测试用例 说明:我们小组就不使用测试管理工具了,直接用excel文件的形式记录,具 ...
- Go 语言并发笔记
前言: 本文是学习<<go语言程序设计>> -- 清华大学出版社(王鹏 编著) 的2014年1月第一版 做的一些笔记 , 如有侵权, 请告知笔者, 将在24小时内删除, 转载请 ...