题目
N,M大小为1e5
思考
通过观察,实际上我们可以把问题转化为和
,
,
,
比较有多少个相等,有多少个大于,有多少个小于,需要在的复杂度中求解这个问题
什么时候,
进入循环呢?也就是
,
显然,KN==LCM(N,M),所以只需要在LCM的长度中求解上述问题就好了
因为LCM可能还是会超时,所以再把范围缩减到M,找到M中和相关联的B
在LCM的长度中,M中的哪些位置出现了呢?
所以可以在的复杂度找到
对应的B,然后采取排序二分的方式,就能够解决上述问题
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+1;
typedef long long ll;
ll win=0,lose=0,draw=0;
ll g;
vector<vector<int>> divideB;
int gcd(int a,int b){
if(b==0)
return a;
return gcd(b,a%b);
}
void solve(vector<int>& ve,int target){
//stable_sort(ve.begin(),ve.end());
auto lower=lower_bound(ve.begin(),ve.end(),target);
auto upper=upper_bound(ve.begin(),ve.end(),target);
int low=lower-ve.begin()-1;
int high=upper-ve.begin();
int cap=ve.size();
win+=low+1;
lose+=cap-high;
draw+=high-low-1;
}
int main(){
freopen("cardgame.in","r",stdin);
freopen("cardgame.out","w",stdout);
cin.tie(0);
ios::sync_with_stdio(0);
int N,M;
cin>>N>>M;
int A[N+1],B[M+1];
g=gcd(N,M);
for(int i=0;i<N;i++){
cin>>A[i];
}
divideB.resize(g);
for(int i=0;i<M;i++){
cin>>B[i];
divideB[i%g].push_back(B[i]);
}
for (int i = 0; i < g; i++) {
sort(divideB[i].begin(), divideB[i].end());
}
for(int i=0;i<N;i++){
solve(divideB[i%g],A[i]);
}
win*=g;
lose*=g;
draw*=g;
cout<<win<<'\n'<<lose<<'\n'<<draw<<'\n';
return 0;
}