「杂烩」精灵魔法(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\)老猫查阅 ...
随机推荐
- java实现第五届蓝桥杯奇怪的分式
奇怪的分式 题目描述 上小学的时候,小明经常自己发明新算法.一次,老师出的题目是: 1/4 乘以 8/5 小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (参见图1.png) 老师刚想批 ...
- Spring Data JPA入门及深入
一:Spring Data JPA简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问 ...
- opencl(6)读写传输命令、内存映射命令
1:将缓存对象的内容读到缓存对象中(从设备到主机) cl_int clEnqueuReadBuffer( cl_command_queue command_queue, //命令队列 cl_mem b ...
- struts用action的属性接收参数
新建一个javaweb项目 在项目中加入Struts.xml( 选中项目右键MyEclipse-->project facets-->Struts2-->finish) 在src项目 ...
- javafx分别设置四个边框
package border; import javafx.application.Application; import javafx.geometry.Insets; import javafx. ...
- 线性代数的28法则:作为程序员掌握这些API就够用了……
目录 1. 向量 & 矩阵 1.1. 问: np.ndarray 与 np.matrix 的区别 1.2. 向量空间 2. 算术运算 2.1. 为什么线性代数定义的乘积运算不按照加法的规则(按 ...
- ZWave对COMAND CLASS的处理流程
文章主题 在开发一个 ZWave Device 的过程中,对 COMAND CLASS(单词太长了,后面就简写为 CC 啦) 的处理是最基本.最重要的工作.这篇文章以最最简单的 CC:COMMNAD ...
- Python基础002---基础知识
一.标识符 标识符是自己定义的,是开发人员在程序中自己定义的一些符号和名称,如变量名.函数名等.在 Python 里,标识符由字母(区分大小写).数字.下划线组成,且数字不能开头.常用的命名方法有小驼 ...
- 【JMeter_14】JMeter逻辑控制器__交替控制器<Interleave Controller>
交替控制器<Interleave Controller> 业务逻辑: 根据被控制器触发执行次数,去依次执行控制器下的子节点<逻辑控制器.采样器>. 被触发执行可以由线程组的线程 ...
- [问题解决]Windows下python中pydoc命令提示“'pydoc' 不是内部或外部命令,也不是可运行的程序 或批处理文件。”
解决方法:python -m pydoc 例:python -m pydoc print