题目一:E. Infinite Inversions

这个题目没什么思维量,还比较简单,就是离散化要加上每一个值的后面一个值,然后每一个值放进去的不是1 ,而是这个值与下一个点的差值。

因为这个数代表了一堆数,然后每一次的找到了的逆序对都要乘以这个num。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 4e5 + ;
typedef long long ll;
int num[maxn], a[maxn], b[maxn];
pair<ll, ll>ex[maxn];
struct node {
int l, r;
int num;
}tree[ * maxn];
 
 
void build(int id, int l, int r) {
tree[id].l = l;
tree[id].r = r;
if (l == r) {
tree[id].num = ;
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
}
 
int query(int id, int x, int y) {
int l = tree[id].l;
int r = tree[id].r;
if (x <= l && y >= r) {
return tree[id].num;
}
int ans = ;
int mid = (l + r) >> ;
if (x <= mid) ans += query(id << , x, y);
if (y > mid) ans += query(id << | , x, y);
return ans;
}
 
void push_up(int id) {
tree[id].num =tree[id << ].num+tree[id << | ].num;
}
 
void update(int id, int x, int val) {
int l = tree[id].l;
int r = tree[id].r;
if (l == r) {
//printf("id=%d x=%d val=%d\n", id, x, val);
tree[id].num = val;
return;
}
int mid = (l + r) >> ;
if (x <= mid) update(id << , x, val);
else update(id << | , x, val);
push_up(id);
}
 
int main() {
int n, tot = ;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
int u, v;
scanf("%d%d", &u, &v);
ex[i] = make_pair(u, v);
a[tot++] = u, a[tot++] = v;
a[tot++] = u + , a[tot++] = v + ;
}
sort(a, a + tot);
int len = unique(a, a + tot) - a;
//printf("len=%d\n", len);
num[len - ] = ;
for (int i = ; i < len - ; i++) {
num[i] = a[i + ] - a[i];
//printf("num[%d]=%d a[%d]=%d\n", i, num[i], i, a[i]);
}
memcpy(b, a, sizeof(a));
for(int i=;i<=n;i++)
{
ex[i].first = lower_bound(a, a + len, ex[i].first) - a;
ex[i].second = lower_bound(a, a + len, ex[i].second) - a;
//printf("ex[%d] %lld %lld\n", i, ex[i].first, ex[i].second);
}
for (int i = ; i <= n; i++) swap(a[ex[i].first], a[ex[i].second]), swap(num[ex[i].first], num[ex[i].second]);
ll ans = ;
build(, , len);
for(int i=;i<len;i++)
{
int l = lower_bound(b, b + len, a[i]) - b + ;
//printf("l=%d\n", l);
ans += query(, l, len) * 1ll * num[i];
update(, l, num[i]);
//printf("ans=%lld\n", ans);
}
printf("%lld\n", ans);
return ;
}

离散化+线段树

今天20190809来补一下这个题目的树状数组,一直都没有学过树状数组,今天浅显的学习了一下,学习网站https://www.cnblogs.com/xenny/p/9739600.html

这个讲的还是很详细也很容易理解。

这个还是照着上面的思路,只是把线段树换成树状数组。

今天感觉自己傻了,这个树状数组容易写,但是下面的这个离散化写搓了,这个num数组应该记录的是这个数带这五个数的后面一位有多少个

而不可以是这个数和这个数的前面一位之间有多少个,因为这个比这个数小的肯定比大于这个数的数小,所以肯定是可以构成逆序对的。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 4e5 + ;
int n;
ll c[maxn]; //对应原数组和树状数组 int lowbit(int x) {
return x & (-x);
} void updata(int i, ll k) { //在i位置加上k
while (i <= n) {
c[i] += k;
i += lowbit(i);
}
} ll getsum(int i) { //求A[1 - i]的和
ll res = ;
while (i > ) {
res += c[i];
i -= lowbit(i);
}
return res;
} ll num[maxn];
ll b[maxn], a[maxn];
struct node {
int l, r;
node(int l = , int r = ) :l(l), r(r) {}
}ex[maxn]; int main() {
int m, tot = ;
scanf("%d", &m);
for (int i = ; i <= m; i++) {
int l, r;
scanf("%d%d", &l, &r);
ex[i] = node(l, r);
b[++tot] = l; b[++tot] = l + ;
b[++tot] = r; b[++tot] = r + ;
}
sort(b + , b + + tot);
n = unique(b + , b + + tot) - b - ;
num[n] = ;
for (int i = ; i < n; i++) {
num[i] = b[i + ] - b[i];
}
memcpy(a, b, sizeof(b));
for (int i = ; i <= m; i++) {
ex[i].l = lower_bound(b + , b + + n, ex[i].l) - b;
ex[i].r = lower_bound(b + , b + + n, ex[i].r) - b;
}
for (int i = ; i <= m; i++) {
swap(a[ex[i].l], a[ex[i].r]), swap(num[ex[i].l], num[ex[i].r]);
}
ll ans = ;
for (int i = ; i <= n; i++) {
int l = lower_bound(b + , b + + n, a[i]) - b;
ll res = getsum(n) - getsum(l);
ans += res * num[i];
updata(l, num[i]);
}
printf("%lld\n", ans);
return ;
}

树状数组

题目二:E. Physical Education Lessons

这个空间开的特别变态,空间要开的很大,而且这个空间给的也不是很多,没什么思维量,比较简单。

开始在第17发 re到我怀疑我写搓了,然后就是第一发mle。。。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn1 = 1e7 + 5e6 + ;
const int maxn = 3e5 + ;
typedef long long ll;
int a[maxn * ], num[maxn1];
struct edge {
int u, v, opt;
edge(int u = , int v = , int opt = ) :u(u), v(v), opt(opt) {}
}order[maxn * ];
struct node {
int lazy;
int sum, num;
}tree[maxn1];
 
void push_up(int id) {
tree[id].sum = tree[id << ].sum + tree[id << | ].sum;
tree[id].num = tree[id << ].num + tree[id << | ].num;
}
 
void build(int id, int l, int r) {
tree[id].lazy = -;
if (l == r) {
tree[id].sum = num[l];
tree[id].num = num[l];
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
push_up(id);
}
 
void push_down(int id) {
if (tree[id].lazy != -) {
tree[id << ].sum = tree[id << ].num*tree[id].lazy;
tree[id << | ].sum = tree[id << | ].num*tree[id].lazy;
tree[id << ].lazy = tree[id].lazy;
tree[id << | ].lazy = tree[id].lazy;
tree[id].lazy = -;
}
}
 
void update(int id,int l,int r, int x, int y, int k) {
push_down(id);
if (x <= l && y >= r) {
tree[id].lazy = k;
tree[id].sum = tree[id].num*k;
return;
}
int mid = (l + r) >> ;
if (x <= mid) update(id << , l, mid, x, y, k);
if (y > mid) update(id << | , mid + , r, x, y, k);
push_up(id);
}
 
int main() {
int n, m, tot = ;
scanf("%d%d", &n, &m);
a[] = ;
for (int i = ; i <= m; i++) {
int u, v, k;
scanf("%d%d%d", &u, &v, &k);
order[i] = edge(u, v, k);
a[tot++] = u, a[tot++] = u + ;
a[tot++] = v, a[tot++] = v + ;
}
sort(a, a + tot);
int len = unique(a, a + tot) - a;
for (int i = ; i <= m; i++) {
order[i].u = lower_bound(a, a + len, order[i].u) - a + ;
order[i].v = lower_bound(a, a + len, order[i].v) - a + ;
}
num[len] = n - a[len - ] + ;
for (int i = ; i < len - ; i++) {
num[i + ] = a[i + ] - a[i];
//printf("num[%d]=%d\n", i + 1, num[i + 1]);
}
//for (int i = 1; i <= len; i++) printf("i=%d %d\n",i, num[i]);
build(, , len);
//printf("len=%d\n", len);
for (int i = ; i <= m; i++) {
int l = order[i].u;
int r = order[i].v;
int k = order[i].opt;
//printf("l=%d r=%d\n", l, r);
if (l > r) swap(l, r);
update(,,len, l, r, k - );
ll ans = tree[].sum;
printf("%lld\n", ans);
}
return ;
}

离散化+线段树

线段树 离散化 E. Infinite Inversions E. Physical Education Lessons的更多相关文章

  1. E. Physical Education Lessons 动态开辟线段树区间更新

    E. Physical Education Lessons time limit per test 1 second memory limit per test 256 megabytes input ...

  2. POJ 2528 Mayor's posters(线段树+离散化)

    Mayor's posters 转载自:http://blog.csdn.net/winddreams/article/details/38443761 [题目链接]Mayor's posters [ ...

  3. poj 2528 Mayor's posters(线段树+离散化)

    /* poj 2528 Mayor's posters 线段树 + 离散化 离散化的理解: 给你一系列的正整数, 例如 1, 4 , 100, 1000000000, 如果利用线段树求解的话,很明显 ...

  4. [poj2528] Mayor's posters (线段树+离散化)

    线段树 + 离散化 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayor ...

  5. [UESTC1059]秋实大哥与小朋友(线段树, 离散化)

    题目链接:http://acm.uestc.edu.cn/#/problem/show/1059 普通线段树+离散化,关键是……离散化后建树和查询都要按照基本法!!!RE了不知道多少次………………我真 ...

  6. poj 2528 Mayor's posters 线段树+离散化技巧

    poj 2528 Mayor's posters 题目链接: http://poj.org/problem?id=2528 思路: 线段树+离散化技巧(这里的离散化需要注意一下啊,题目数据弱看不出来) ...

  7. BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针

    BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...

  8. D - Mayor's posters(线段树+离散化)

    题目: The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campai ...

  9. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

随机推荐

  1. AJ学IOS(51)多线程网络之GCD下载合并图片_队列组的使用

    AJ分享,必须精品 合并图片(图片水印)第一种方法 效果 实现: 思路: 1.分别下载2张图片:大图片.LOGO 2.合并2张图片 3.显示到一个imageView身上 // 异步下载 dispatc ...

  2. 高级工程师-Java注解

    高级工程师-Java注解 前言 代码,就是我们身为程序员的名片. 简洁,优雅,统一,是我们的追求. 优秀的代码,会给浏览者一种艺术的美感.如DL大神的JUC包,感兴趣的小伙伴,可以研究一下. 那么日常 ...

  3. Linux命令:chown

    说明: 将指定文件的拥有者改为指定的用户或组. 语法: chown [-cfhvR] [--help] [--version] user[:group] file... 参数: user : 新的文件 ...

  4. 详解 字符串—— String、StringBuffer 与 StringBuilder

    本来这篇博文的内容,本人打算在之后的代码中一点一点通过实例讲解的,但是,本人发现,其实这里的知识点还是蛮重要的. 并且,字符串类型,在任何的程序语言中都是被认真对待的,所以,今天专门写一篇博文来介绍一 ...

  5. Apache solr velocity模块 漏洞复现

    0x01 Solr简单介绍 Solr是建立在Apache Lucene ™之上的一个流行.快速.开放源代码的企业搜索平台. Solr具有高度的可靠性,可伸缩性和容错能力,可提供分布式索引,复制和负载平 ...

  6. [linux] linux的top命令参数详解

    简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按 ...

  7. 常问的MySQL面试题整理

    char.varchar 的区别是什么? varchar是变长而char的长度是固定的.如果创建的列是固定大小的,你会得到更好的性能 truncate 和 delete 的区别是什么? delete ...

  8. 设计模式 - 命令模式详解及其在JdbcTemplate中的应用

    基本介绍 在软件设计中,我们经常需要向某些对象发送一些请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需要在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来设计,使得 ...

  9. python工业互联网监控项目实战4—python opcua

    前面章节我们采用OPC作为设备到上位的信息交互的协议,本章我们介绍跨平台的OPC UA.OPC作为早期的工业通信规范,是基于COM/DCOM的技术实现的,用于设备和软件之间交换数据,最初,OPC标准仅 ...

  10. Websec level 30

    前言 昨天在易霖博搞的网络安全与执法竞赛看到的一道web题,实际上就是用两个原题凑起来的.. 不过后面的一关没见过这里简单记录一下 第一关 打开是个登录界面,和BJDCTF的简单注入一模一样,连密码都 ...