http://codeforces.com/problemset/problem/387/E
记录每个数的下标,对数从小到大考虑。如果该数需要保留,那么就往set中插入该数的下标。否则可以查询出当前数左边和右边第一个比它小的数的下标,可以统计这个区间中已经删掉的数的数量,就可以计算出当前数的贡献。
#include<bits/stdc++.h>
using namespace std;
const int MAX_LEN = 1e6+10;
typedef long long ll;
int n, m;
ll tree[MAX_LEN];
int id[MAX_LEN], keep[MAX_LEN];
void add(int pos, int value){
while(pos <= n){
tree[pos] += value;
pos += (pos&-pos);
}
return ;
}
ll query(int l, int r){
int ans = 0;
while(r){
ans += tree[r];
r -= (r&-r);
}
while(l){
ans -= tree[l];
l -= (l&-l);
}
return ans;
}
set<int> se;
set<int> reverseSe;
int main(){
std::ios::sync_with_stdio(false);
memset(keep, false, sizeof(keep));
scanf("%d%d",&n, &m);
int tmp;
for (int i = 1; i <= n; i++)
scanf("%d", &tmp), id[tmp] = i;
for (int i = 1; i <= m; i++)
scanf("%d", &tmp), keep[tmp] = true;
se.insert(0); se.insert(n+1);
reverseSe.insert(0); reverseSe.insert(-n-1);
if (n == m){
cout << 0 << endl;
return 0;
}
ll ans = 0;
for (int i = 1; i <= n; i++){
if (keep[i])
se.insert(id[i]), reverseSe.insert(-id[i]);
else{
int l = -*reverseSe.upper_bound(-id[i]);
int r = *se.upper_bound(id[i]);
//cout << "l: " << l << " r: " << r << endl;
ans += r-l-1;
ans -= query(l, r-1);
add(id[i], 1);
}
}
printf("%I64\n", ans);
return 0;
}