单调队列,对于打卡顺序进行进队列和出队列操作,进队列的数为a[i]号员工的下班打卡时间,如果该员工不在单调队列就说明该员工暂未上班打卡,而队列中的数则为已经上班打卡,但未下班打卡的人,这些人有可能取代该员工。如果这员工的下班时间晚于单调队列最右侧的人的下班时间,说明其下班时间晚于该单调队列里所有人的下班时间,否则就必然存在该单调队列最右侧的人可以代替该员工的情况。弹出单调队列左侧下班时间超过当前时间的人。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,a[N<<1];
int t[N<<1],q[N],ans;//t记录每人下班时间
bool h[N];
int main(){
freopen("giligili.in","r",stdin);
freopen("giligili.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n<<1;i++){
cin>>a[i];
t[a[i]]=i;
}
int l=1,r=1;//队头和队尾
q[l]=t[a[1]];
h[a[1]]=1;
for(int i=2;i<=n<<1;i++){
while(q[l]<i && l<=r){//
l++;
}
if(!h[a[i]]){
h[a[i]]=1;
if(l>r){
q[++r]=t[a[i]];
}else{
if(q[r]>t[a[i]])ans++;
else q[++r]=t[a[i]];
}
}
}
cout<<ans<<endl;
return 0;
}