这一题有点意思
首先预处理出 $pos[x]$ 表示编号 $x$ 的车是第几个出隧道的
然后按进入隧道的顺序枚举每辆车 $x$ 考虑有哪些车比 $x$ 晚进入隧道却比 $x$ 早出隧道
显然是 $1$ 到 $pos[x]$ 中还没访问过的车,那么暴力做法就是这样枚举然后看看有哪些没标记并打上标记
注意到每辆车只要打上一个标记即可,并且每次打标记都只在一段前缀区间内
那么维护一下 $r$ 表示之前打标记的区间的最右端,每次只要考虑 $[r,pos[x]]$ 即可(注意 $pos[x]$ 本身不用打标记,不产生贡献)
均摊复杂度 $O(n)$(代码实现时可以省略标记数组)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e5+7; int n,pos[N]; struct dat { int x,y; inline bool operator < (const dat &tmp) const { return x!=tmp.x ? x<tmp.x : y<tmp.y; } }A[N]; bool vis[N]; int main() { n=read(); int ans=0; for(int i=1;i<=n;i++) A[i].x=read(); for(int i=1;i<=n;i++) A[i].y=read(),pos[A[i].y]=i; int l=1,r=0; for(int i=1;i<=n;i++) { r=max(r,pos[A[i].x]); for(int k=l;k<r;k++) { ans++; vis[A[k].y]=1; } l=r+1; } printf("%d\n",ans); return 0; }