Description

小 a有一个长度无限长的序列 p = (1, 2, 3, 4 ……),初始时 pi = i

给出 m 个操作,每次交换两个位置的数

询问最后序列逆序对的个数

Solution

忘了可以树状数组直接做了.所以写了很麻烦的线段树.

大概写一下怎么做, 因为细节比较多.

我们发现一次交换的实际上是交换了两个位置上的数.

我们可以将所有的位置分成三类:

  • 有的位置会被改变(交换), 也对答案有贡献;

  • 有的位置不会被改变, 也不会对答案有贡献;

  • 有的位置不会被改变, 但是对答案有贡献.

  • 第一类是所有的操作会交换的位置;

  • 第二类是被改变的第一个和最后一个位置往左和往右的数;

  • 第三类是不会被直接改变, 但是其左右都有被改变的数.

举个例子:交换2和5位置, 数列变成\(1,5,3,4,2,6,7,\cdots\).

位置\(2, 5\)属于第一类, 位置\(1,6,7,\cdots\)属于第二类, 位置\(3, 4\)属于第三类(因为与5位置形成逆序对)

  • 对于不会被改变也没有影响的数, 忽略存在就好了.
  • 对于不会被改变但是有影响的位置, 这些位置的行为表现出来像是一个整体(会同时对另一个位置产生或不产生逆序对).

    所以就把他们起来, 看成是一个特殊的数字就好了.

所以就将这些涉及到的位置离散化, 在离散化后按要求交换这些位置上的数形成一个数列,利用树状数组/线段树求逆序对即可.

至于怎么离散化, 看代码就好了

Code

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e6;
struct Node {
long long val;
Node *ls, *rs;
Node(int _v = 0, Node *_ls = nullptr, Node *_rs = nullptr) :
val(_v), ls(_ls), rs(_rs) { }
void pushup() {
val = ls->val + rs->val;
}
void mod(int k) { val += k; }
};
class Tree { // 普通的单调修改区间查询线段树
int n;
Node* root;
#define LS l, mid, node->ls
#define RS mid + 1, r, node->rs
void build(int l, int r, Node* node) {
if (l == r) return;
int mid = l + r >> 1;
node->ls = new Node();
node->rs = new Node();
build(LS), build(RS);
}
void insert(int l, int r, Node* node, int p, int k) {
if (l == r) return node->mod(k);
int mid = l + r >> 1;
if (p <= mid) insert(LS, p, k);
if (p > mid) insert(RS, p, k);
node->val = node->ls->val + node->rs->val;
}
long long query(int l, int r, Node* node, int L, int R) {
if (l >= L and r <= R)
return node->val;
int mid = l + r >> 1;
long long res = 0;
if (L <= mid) res += query(LS, L, R);
if (R > mid) res += query(RS, L, R);
return res;
}
public:
Tree(int _n) : n(_n), root(new Node()) {}
void build() {
build(1, n, root);
}
long long query(int l, int r) {
return query(1, n, root, l, r);
}
void insert(int p, int k) {
insert(1, n, root, p, k);
}
};
struct Operate {
int l, r;
Operate(int _ = 0, int __ = 0) :
l(_), r(__) {}
}Opt[N];
struct Element {
int v, siz;
Element(int _v = 0, int _s = 0) :
v(_v), siz(_s) { }
bool operator < (const Element& o) const {
return v < o.v;
}
}P[N]; int A[N], seq[N]; int main () {
int n;
scanf("%d", &n);
int tot = 0;
for (int i = 1, u, v, c; i <= n; i += 1) {
scanf("%d%d", &u, &v);
Opt[i] = Operate(u, v);
A[++tot] = u, A[++tot] = v;
}
sort(A + 1, A + tot + 1);
int cnt = unique(A + 1, A + tot + 1) - A - 1; // 被直接交换的位置, 也就是第一类
int total = 0;
for (int i = 1; i <= cnt; i += 1) {
P[++total] = Element(A[i], 1); // 第一类
if (A[i + 1] > A[i] + 1) // A[i] 和A[i+1]之间的是第三类
P[++total] = Element(A[i] + 1, A[i + 1] - A[i] - 1); // A[i+1]-A[i]-1是这一段的个数
}
#define Find(x) lower_bound(P + 1, P + total + 1, Element(x, 0)) - P
Tree* T = new Tree(total); // 建线段树
T->build();
for (int i = 1; i <= total; i += 1)
seq[i] = i;
for (int i = 1, u, v; i <= n; i += 1) {
u = Find(Opt[i].l), v = Find(Opt[i].r); // 按要求交换
swap(seq[u], seq[v]);
}
long long res = 0;
for (int i = 1; i <= total; i += 1) {
T->insert(seq[i], P[seq[i]].siz);
res += 1ll * P[seq[i]].siz * T->query(seq[i] + 1, total);
}
printf("%lld\n", res);
return 0;
}

P2448 无尽的生命的更多相关文章

  1. P2448 无尽的生命(树状数组+离散化)

    题目描述 逝者如斯夫,不舍昼夜! 叶良辰认为,他的寿命是无限长的,而且每天都会进步. 叶良辰的生命的第一天,他有1点能力值.第二天,有2点.第n天,就有n点.也就是S[i]=i 但是调皮的小A使用时光 ...

  2. 杂项 List

    题目 1. 栈    #A 表达式的转换 (Unaccepted) 2. STL 模板库 #B 双栈排序(Unaccepted)    #C 垃圾陷阱(Accepted)    #D 合并果子(Acc ...

  3. Linux内核同步

    Linux内核剖析 之 内核同步 主要内容 1.内核请求何时以交错(interleave)的方式执行以及交错程度如何. 2.内核所实现的基本同步机制. 3.通常情况下如何使用内核提供的同步机制. 内核 ...

  4. Unity脚本生命周期

    前言 说到生命周期,影响最深刻的是,在接触Java的JSF组件时,JSF组件的五大生命周期,全要默写出来,嘿嘿…… 总结这两天在写小怪和掉落的糖葫芦时,老是遇到GameObject未销毁,一直存在场景 ...

  5. GPU大百科全书 第二章 凝固生命的光栅化

    光栅化——死神来了……   前言:在上一期的GPU大百科全书里,我们目睹了可爱的香草从抽象世界走向现实,从方程还原成实体的全过程.可以说香草活了,因为几何单元,我们赋予了她完整的灵魂. 如果你正在为G ...

  6. 从BeanFactory源码看Bean的生命周期

    下图是我搜索"Spring Bean生命周期"找到的图片,来自文章--Spring Bean的生命周期 下面,我们从AbstractAutowireCapableBeanFacto ...

  7. react组件的生命周期

    写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...

  8. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  9. C# MVC 5 - 生命周期(应用程序生命周期&请求生命周期)

    本文是根据网上的文章总结的. 1.介绍 本文讨论ASP.Net MVC框架MVC的请求生命周期. MVC有两个生命周期,一为应用程序生命周期,二为请求生命周期. 2.应用程序生命周期 应用程序生命周期 ...

随机推荐

  1. 【bzoj3881】【Coci2015】Divljak

    题解 对$S$集合ac建自动机,把$T_{i}$放在里面跑,记录路径上的所有节点并对它们在fail树上求到root的树链并: 这样就得到了$T_{i}$所有的子串: 动态将$T_{i}$加入直接用树状 ...

  2. 关于strassen矩阵乘法的矩阵大小不是2^k的形式时,时间复杂度是否还是比朴素算法好的看法

    原来是n,找到大于等于n且是2^k形式的数m.n*n的矩阵补全为m*m的矩阵,原来的矩阵放在最左上方,其它位置的值为0.朴素方法:n^3现在:m^2.8即m/n需小于e^(3/2.8)=2.919才能 ...

  3. 常用Build-in Keywords

    1. Variables |- Set variable |- Create list |- Evaluate |- Get Variable Value 2. Conditional |- Run ...

  4. pre-processing预处理

    什么是神经网络?神经网络是由很多神经元组成的,首先我们看一下,什么是神经元1.我们把输入信号看成你在matlab中需要输入的数据,输进去神经网络后2.这些数据的每一个都会被乘个数,即权值w,然后这些东 ...

  5. Java 从业一年的心得体会

    在你打开此文时,你或许在犹豫这个职业,但是我觉得干就好了,没有适合不适合,趁年轻折腾吧! 以下是我一年来从事Java的经验积累,知识有很多,经验就九条 1.设计的数据库表尽量添加一个状态位,可以在删除 ...

  6. my-innodb-heavy-4G.cnf配置文件注解

    [client] ####客户端 port = 3306 ####mysql客户端连接时的默认端口号 socket = /application/mysql-5.5.32/tmp/mysql.sock ...

  7. Linux查看服务器公网ip的方法

    在解决网络问题时,需要查看本机的出口公网IP信息,有如下两个方法: curl ifconfig.me 在linux系统中输入上述的命令,可以查看到本机连接的公网信息: 如果该命令无效,可以使用下面一个 ...

  8. [HTML5和Flash视频播放器]Video.js 学习笔记(一 ) HLS库:videojs-contrib-hls

    DEMO地址:https://github.com/Tinywan/PHP_Experience https://github.com/videojs/videojs-contrib-hls 下载JS ...

  9. excel sum求和遇到的问题及解决

    在偶遇的,借助excel公式sum对一个数字数组进行求和,结果为0,很是诧异,当然原因就是,数组里的数字是“常规”格式,不是“数值”格式,由于系统生成的excel,不方便生成的同时再做格式的设置,于是 ...

  10. 苏宁OLAP架构设计

    一. 功能综述 OLAP引擎为存储和计算二合一的引擎,自身内部涵盖了对数据的管理以及提供查询能力.底层数据完全规划在引擎内部,外部系统不允许直接操作底层数据,而是需要通过暴露出来的接口来读写引擎内部数 ...