随笔(一)
今天老师在微信群里发了一个研究生复试的题,让我们看了看,不难。大概意思就是,有n辆车进隧道,隧道禁止超车,进入的顺序是
1
−
n
1 -n
1−n,出来的顺序是一个包含n个不重复整数的序列,例如出来的是
4 3 2 1
判断隧道中有多少辆车超车了。
文件中,有一个不知名的学长的代码,有点问题(岂止有点问题,问题好多好嘛,爆栈+TLE),我看了一眼,woc,这不就是一个和逆序数有关的sb题吗。树状数组搞一下,貌似没问题(也确实没问题)。
N
l
o
g
2
N
Nlog_2N
Nlog2N本来以为很优秀了,然后问了东哥,东哥给了一个
O
(
N
)
O(N)
O(N)的算法,(%%%
l
d
s
lds
lds)然后呢,我也思考了一下下,
O
(
N
)
O(N)
O(N)没问题,然后我发现
O
(
N
)
O(N)
O(N)貌似有第二种代码方式,写了一下。惊!这个不对??这是为啥??
思索半天,毫无头绪。。出门走走吧,万一就懂了呢 果不其然,这一出门走了那么几步,有思路。。兴奋的我拿起纸笔开始研究,写着写着,woc我刚刚想错了,真tmsb。。
然后在蹲在那想啊想啊,到了该吃饭的时间,突然又懂了。这次是真的懂了 然后吃完饭来写blog了。hh
两个不同的解法都会说的。
解法一:魔改逆序
首先,假设进来的序列是从小到大的,即1,2,3,,,n,后面如果有车辆超车,一定会出现逆序,因此只需要在求逆序的时候,不真正求逆序,而是判断该车辆是否有逆序产生,当然,有要求的。。。。逆序的定义必须按照,每一个数字后面有几个比自己小的算(有点苛刻,但是第二个解法也必须用这一点)
code:
#include <stdio.h>
const int N = 100100;
int c[N];
int n;
int icar[N], irealcar[N];
int ocar[N], orealcar[N];
int lowbit(int x){
return x & -x;
}
void add(int ind, int x){
while (ind <= n){
c[ind] += x;
ind += lowbit(ind);
}
}
int query(int x){
int sum = 0;
while (x > 0){
sum += c[x];
x -= lowbit(x);
}
return sum;
}
int main()
{
freopen("in.in", "r", stdin);
freopen("o1.out", "w", stdout);
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", icar + i);
irealcar[icar[i]] = i;
}
for (int i = 1; i <= n; i++){
scanf("%d", ocar + i);
orealcar[i] = irealcar[ocar[i]];
}
int ans = 0;
int res = 0;
for (int i = n; i >= 1; i--){
int t = ans;
ans += query(orealcar[i] - 1);
if (t != ans)res++;
add(orealcar[i], 1);
}
printf("%d\n", res);
return 0;
}
解法二:从第一个解法可以发现,我们不关心有多少个逆序数,只关心是否产生逆序,因此可以
O
(
N
)
O(N)
O(N),如果一辆车超车了,那么它后面一定有一个编号小于它的车存在,相反,它前面如果编号比它大的,只能说明它被超越了,并不能知道有几辆车超车了,因此必须这样求解了,这也是为什么树状数组逆序可以求,归并则不一定。然后就是用一个min表示当前最小值,
O
(
N
)
O(N)
O(N)循环一次即可。
code:
#include <stdio.h>
int a[100100], b[100100];
int n;
int main()
{
freopen("in.in", "r", stdin);
freopen("o3.out", "w", stdout);
scanf("%d", &n);
for (int i = 1; i <= n; i++){
int t;
scanf("%d", &t);
a[t] = i;
}
for (int i = 1; i <= n; i++){
int t;
scanf("%d", &t);
b[i] = a[t];
}
int mn = 0x3f3f3f3f;
int ans = 0;
for (int i = n; i >= 1; i--){
if (b[i] > mn)ans++;
if (mn > b[i])mn = b[i];
}
printf("%d\n", ans);
return 0;
}
%%% l d s lds lds
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/16548412.html

浙公网安备 33010602011771号