P2448 无尽的生命
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 无尽的生命的更多相关文章
- P2448 无尽的生命(树状数组+离散化)
题目描述 逝者如斯夫,不舍昼夜! 叶良辰认为,他的寿命是无限长的,而且每天都会进步. 叶良辰的生命的第一天,他有1点能力值.第二天,有2点.第n天,就有n点.也就是S[i]=i 但是调皮的小A使用时光 ...
- 杂项 List
题目 1. 栈 #A 表达式的转换 (Unaccepted) 2. STL 模板库 #B 双栈排序(Unaccepted) #C 垃圾陷阱(Accepted) #D 合并果子(Acc ...
- Linux内核同步
Linux内核剖析 之 内核同步 主要内容 1.内核请求何时以交错(interleave)的方式执行以及交错程度如何. 2.内核所实现的基本同步机制. 3.通常情况下如何使用内核提供的同步机制. 内核 ...
- Unity脚本生命周期
前言 说到生命周期,影响最深刻的是,在接触Java的JSF组件时,JSF组件的五大生命周期,全要默写出来,嘿嘿…… 总结这两天在写小怪和掉落的糖葫芦时,老是遇到GameObject未销毁,一直存在场景 ...
- GPU大百科全书 第二章 凝固生命的光栅化
光栅化——死神来了…… 前言:在上一期的GPU大百科全书里,我们目睹了可爱的香草从抽象世界走向现实,从方程还原成实体的全过程.可以说香草活了,因为几何单元,我们赋予了她完整的灵魂. 如果你正在为G ...
- 从BeanFactory源码看Bean的生命周期
下图是我搜索"Spring Bean生命周期"找到的图片,来自文章--Spring Bean的生命周期 下面,我们从AbstractAutowireCapableBeanFacto ...
- react组件的生命周期
写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- C# MVC 5 - 生命周期(应用程序生命周期&请求生命周期)
本文是根据网上的文章总结的. 1.介绍 本文讨论ASP.Net MVC框架MVC的请求生命周期. MVC有两个生命周期,一为应用程序生命周期,二为请求生命周期. 2.应用程序生命周期 应用程序生命周期 ...
随机推荐
- 团体程序设计天梯赛 L1-011. A-B
读入的是字符串,数组大小至少为字符串长度+1 #include <stdio.h> #include <stdlib.h> #include <string.h> ...
- SystemV-IPC
这里记录的三种SystemV-IPC包括(消息队列,信号量以及共享内存) 1:标识符和键值 键值(key_t) : IPC结构的外部名(所谓外部名就是各用户进程可获得并操作的,通过它使用XXXget获 ...
- 01 C++ 多线程入门实例
1.可复用的完整实例 #include <iostream> #include <thread> #include <mutex> using namespace ...
- 题解 P1967 【货车运输】
树链剖分+线段树 思路 貌似题解里没有树链剖分和线段树的,贡献一发. 首先明确题目要求:一辆车走某条路从x城到y城的边权最小值 我们把要求分开来看: 从x城到y城:我们需要走的路径将两点联通 边权最小 ...
- 《剑指offer》面试题45 圆圈中最后剩下的数字(Java版本)
引言 这道题网上的讲解都是直接抄书,没意思,所以想自己写一写,补充一下,便于自己理解.另外,大家都忽略了经典解法,虽然这种解法效率不及第二种,但是我觉得在项目当中阅读性其实很重要,牺牲一点点效率保证代 ...
- Django 2.0.1 官方文档翻译: 编写你的第一个 Django app,第七部分(Page 12)
编写你的第一个 Django app,第七部分(Page 12)转载请注明链接地址 本节教程承接第六部分(page 11)的教程.我们继续开发 web-poll应用,并专注于自定义django的自动生 ...
- JAVA多线程提高十四: 面试题
前面针对多线程相关知识点进行了学习,那么我们来来看看常见的面试题: 1. 空中网面试题1 package com.kongzhongwang.interview; import java.util.c ...
- Ex1—vlookup
VLOOKUP 的语法结构 整个计算机就相当于一门语言,首先我们就是要获取该函数的语法结构.以下是官网的语法结构 VLOOKUP(lookup_value, table_array, col_inde ...
- HDFS的java接口——简化HDFS文件系统操作
今天闲来无事,于是把HDFS的基本操作用java写出简化程序出来给大家一些小小帮助! package com.quanttech; import org.apache.hadoop.conf.Conf ...
- ubuntu 开机自动挂在windows下的分区
最近装了Ubuntu14.04 + windows7 的双系统,启动Ubuntu的时候,不会自动挂载win7的分区,只有我点击相应的硬盘符号时才会挂载/media下面.本着折腾到底的原则,在网上搜了搜 ...