「杂烩」精灵魔法(P1908逆序对弱化版)
「杂烩」精灵魔法(P1908逆序对弱化版)
题面:
题目描述
\(Tristan\)解决了英灵殿的守卫安排后,便到达了静谧的精灵领地——\(Alfheim\) 。由于$ Midgard$ 处在$ Alfheim\(和冥界\) Hel$ 的中间,精灵族领地尚未受到冥界恶灵的侵入。族长$ Galanodel \(为了帮助米德加尔特抵御外敌,对邪恶亡灵军团使用了高等魔法,从而使得亡灵军团每个士兵的行进速度变得不一致,从而打乱冥王\)Hel$安排的最佳阵型。
由于这个军团离\(Midgard\)还很远,因此在抵达$ Midgard$ 之前,对于$ A,B$ 两个亡灵,若$A \(的初始位置在\) B\(后面且\)A \(的速度比 快,\)A \(就会冲到\)B \(的前面去。现在\)Galanodel$ 想知道,会有多少对亡灵之间出现反超现象?
输入格式
第一行一个整数$ n$,表示排成一队的邪恶亡灵军团有多少人。
第二行\(n\)个整数\(a[i]\),表示邪恶亡灵们在数轴上的初始坐标。数据保证这些坐标全部不同。亡灵军团向数轴正方向前进。
第三行\(n\)个整数 \(v[i]\),表示邪恶亡灵们的行进速度。
输出格式
一行一个正整数\(k\),表示「反超」的个数。
样例
样例输入
3
1 2 3
2 1 3
样例输出
1
数据范围与提示
$ n<= 100000$
所有数据的绝对值均不超过\(maxlongint\)。
解法一:朴素的暴力(50pts)
一看就让我们求排序后的逆序对,\(O(n^2)\)搞它
代码:
/*#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
name=$GEDIT_CURRENT_DOCUMENT_NAME
pre=${name%.*}
g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
if test $? -eq 0; then
gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
fi*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
typedef long long ll;
using namespace std;
const int maxn=1e5+5,INF=0x3f3f3f3f;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}
int n;
ll ans,minn,maxx;
struct Node{
ll d,v;
}a[maxn];
bool cmp(Node A,Node B){return A.d<B.d;}
int main(){
//freopen("a.in","r",stdin);
n=read();
for(int i=1;i<=n;i++)cin>>a[i].d;
for(int i=1;i<=n;i++)cin>>a[i].v;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(a[i].v>a[j].v)ans++;
}
}
cout<<ans;
return 0;
}
解法2:智障的set(40pts)
先介绍个函数:\(algorithm\)库里的\(distance\)函数能够轻易的帮我们把迭代器转成下标处理,用到set上就十分合适
利用set自动排序的功能,可以轻易处理逆序对,将位置从大到小\(sort\)一遍,找新序列的正序对就行了(正序是逆序对,倒序不就是正序对么)
如果新元素比队尾元素大,说明前面所有元素都能于它构成正序对,相反,就可以利用\(lowerbound\)函数找到第一个大于等于它的位置,恰好是它能组成的正序对个数
但是由于set时间效率极低,还没暴力跑的快,用这个练习练习STL就行了
代码:
/*#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
name=$GEDIT_CURRENT_DOCUMENT_NAME
pre=${name%.*}
g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
if test $? -eq 0; then
gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
fi*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
typedef long long ll;
using namespace std;
const int maxn=1e5+5,INF=0x3f3f3f3f;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}
int n,f[maxn];
ll ans;
struct Node{
ll d,v;
}a[maxn];
multiset<int> s;
bool cmp(Node A,Node B){return A.d>B.d;}
int main(){
// freopen("a.in","r",stdin);
n=read();
for(int i=0;i<n;i++)cin>>a[i].d;
for(int i=0;i<n;i++)cin>>a[i].v;
sort(a,a+n,cmp);
s.insert(a[0].v);
f[0]=0;
for(int i=1;i<n;i++){
int len=s.size();
if(a[i].v>=*s.rbegin()){//注意,set的end()是假的,只能这样求队尾元素
f[i]=len,s.insert(a[i].v);
}else{
// cout<<(lower_bound(ve.begin(),ve.end(),a[i].v),a[i].v)<<endl;
f[i]=distance(s.begin(),s.lower_bound(a[i].v));//distance将迭代器转下标
s.insert(a[i].v);
}
//for(int i=0;i<n;i++)cout<<ve[i]<<" ";
//cout<<endl;
}
for(int i=0;i<n;i++)ans+=f[i];
cout<<ans;
return 0;
}
解法3:vector模拟set(100pts)
众所周知,$$vector功能强大,轻易就能排个序,效率比set还高不少,但是终究过不了加强版的P1908
代码:
/*#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
name=$GEDIT_CURRENT_DOCUMENT_NAME
pre=${name%.*}
g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
if test $? -eq 0; then
gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
fi*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
typedef long long ll;
using namespace std;
const int maxn=1e5+5,INF=0x3f3f3f3f;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}
int n,f[maxn];
ll ans;
struct Node{
ll d,v;
}a[maxn];
vector<int> ve;
bool cmp(Node A,Node B){return A.d>B.d;}
int main(){
// freopen("a.in","r",stdin);
n=read();
for(int i=0;i<n;i++)cin>>a[i].d;
for(int i=0;i<n;i++)cin>>a[i].v;//狗比vector只能从0开始存
sort(a,a+n,cmp);
ve.push_back(a[0].v);
f[0]=0;
for(int i=1;i<n;i++){
int len=ve.size();
if(a[i].v>=ve.back()){
f[i]=len,ve.push_back(a[i].v);
}else{
// cout<<(lower_bound(ve.begin(),ve.end(),a[i].v),a[i].v)<<endl;
f[i]=lower_bound(ve.begin(),ve.end(),a[i].v)-ve.begin();//注意写法,考试就在这被卡住了
ve.insert(lower_bound(ve.begin(),ve.end(),a[i].v),a[i].v);//假装排序
}
//for(int i=0;i<n;i++)cout<<ve[i]<<" ";
//cout<<endl;
}
for(int i=0;i<n;i++)ans+=f[i];
cout<<ans;
return 0;
}
解法4:树状数组(100pts)
对结构体\(a[i]\)排序,按位置从小到大的顺序排,利用辅助数组b记录排序后的位置,将位置插入树状数组,咨询一下后缀和即可
代码:
/*#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
name=$GEDIT_CURRENT_DOCUMENT_NAME
pre=${name%.*}
g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
if test $? -eq 0; then
gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
fi*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
typedef long long ll;
using namespace std;
const int maxn=1e5+5,INF=0x3f3f3f3f;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}
int n,f[maxn];
ll ans,b[maxn],c[maxn];
struct Node{
ll d,v;
}a[maxn];
bool cmp(Node A,Node B){return A.d<B.d;}
ll Lowbit(ll x){return x&-x;}
void update(ll x){
while(x<=n){
c[x]++;
x+=Lowbit(x);
}
}
ll query(ll x){
ll sum=0;
while(x){
sum+=c[x];
x-=Lowbit(x);
}
return sum;
}
int main(){
//freopen("a.in","r",stdin);
n=read();
for(int i=1;i<=n;i++)cin>>a[i].d;
for(int i=1;i<=n;i++)cin>>a[i].v,b[i]=a[i].v;
sort(a+1,a+n+1,cmp);
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)a[i].v=lower_bound(b+1,b+1+n,a[i].v)-b;
for(int i=n;i>=1;i--){
ans+=query(a[i].v-1);update(a[i].v);
}
cout<<ans;
return 0;
}
解法5:归并排序(100pts)
这就不用写了吧,归并能处理逆序对(貌似也只有这个用途)
「杂烩」精灵魔法(P1908逆序对弱化版)的更多相关文章
- 「luogu2387」[NOI2014] 魔法森林
「luogu2387」[NOI2014] 魔法森林 题目大意 \(n\) 个点 \(m\) 条边的无向图,每条边上有两个权值 \(a,b\),求从 \(1\) 节点到 \(n\) 节点 \(max\{ ...
- 洛谷P1908 逆序对
P1908 逆序对 2.2K通过 4.4K提交 题目提供者该用户不存在 标签云端 难度普及/提高- 时空限制1s / 128MB 提交 讨论 题解 最新讨论更多讨论 归并排序党注意了!数组要开… ...
- 洛谷P1908 逆序对【递归】
题目:https://www.luogu.org/problemnew/show/P1908 题意:给定一个数组,求逆序对个数. 思路: 是一个很经典的题目了.通过归并排序可以求逆序对个数. 现在有一 ...
- P1908 逆序对-(树状数组)
https://www.luogu.org/problem/P1908 比较喜欢线段树,懒得用树状数组(只会套模板,位运算的精髓没有领悟到),一直没有记录树状数组代码,又得捡回来,趁这道题记录一下模板 ...
- P1908 逆序对-(cdq分治)
https://www.luogu.org/problem/P1908 沿用归并排序的思想求逆序对. 坑1:结果爆int型,需要用longlong 坑2:相对于归并排序,在比较的时候多了一个等号 举例 ...
- P1908 逆序对(归并排序)
https://www.luogu.com.cn/problem/P1908 归并排序是用来求逆序对的 归并排序的思想就是分治 #include <bits/stdc++.h> using ...
- P1908 逆序对——树状数组&离散化&快读快写の学习
题目简述: 对于给定的一段正整数序列,逆序对就是序列中 a_i>a_jai>aj 且 i<ji<j 的有序对. 输出序列中逆序对的数目. 知识补充: 树状数组: 这东西就是 ...
- 洛谷 P1908 逆序对 Label:归并排序||树状数组 不懂
题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定 ...
- 洛谷 P1908 逆序对
\[传送门qwq\] 题目描述 猫猫\(TOM\)和小老鼠\(JERRY\)最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计. 最近,\(TOM\)老猫查阅 ...
随机推荐
- 2018年全国多校算法寒假训练营练习比赛(第二场)H-了断局
题目描述 既然是了断局了,大家就随便玩玩数字呗.已知一个数列前十项分别是{0, 1, 1, 2, 4, 7, 13, 24, 44, 81},小G不满足呀:我要更多的数!!!不给就不让你们玩了.小G会 ...
- CDN百科 | 假如没有CDN,网络世界会变成什么样?
很多人都知道CDN是内容分发加速,所谓内容分发,就是将本来位于源站的内容分发到全国各地的节点,方便用户去就近访问所需的内容.随着移动互联网.云计算等一代代技术变革,CDN已经成为了缓解互联网网络拥塞. ...
- 三、TCP协议
TCP(Transmission Control Protocol)传输控制协议:顾名思义就是对数据的传输进行控制 TCP报头 序号:相当于编号,当TCP数据包过大的时候会进行分段,分段之后按序号顺序 ...
- 使用PyQtGraph绘制图形(1)
首先利用numpy模块创建两个随机数组,用来作为图形绘制的数据: import pyqtgraph as pg import numpy as np x = np.random.random(50) ...
- hiredis window 源码编译
编译工具 cmake mingw730_32 版本 hiredis:0.15 cmake: cmake-3.12.4-win64-x64 mingw: 7.3.0 make配置 注意:D:\Qt\Qt ...
- Jquery封装:下拉框插件
代码如下: ;(function ($, window) { $.fn.addSelect = function (options) { //合并传入与默认的参数 var opts = $.exten ...
- blob斑点检测
目录 1. 可选算法 1.1. Laplacian of Gaussian (LoG) 1.2. Difference of Gaussian (DoG) 1.3. Determinant of He ...
- spark源码分析以及优化
第一章.spark源码分析之RDD四种依赖关系 一.RDD四种依赖关系 RDD四种依赖关系,分别是 ShuffleDependency.PrunDependency.RangeDependency和O ...
- (四)Maven项目工程目录约定
使用maven创建的工程我们称它为maven工程,maven工程具有一定的目录规范,如下: src/main/java 存放项目的.java文件 src/main/resources 存放项目资源文件 ...
- 基于JQuery的简单富文本编辑器
利用jQuery实现最简单的编辑器 我试了很多种方法,目前最快捷能够实现及其简单的编辑可以使用 document.execCommand("ForeColor", "fa ...