-
题意:有一个长度为\(n\)的序列\(a\),求这个序列中有多少比\(a_{i}\)小的数,如果某两个位置上的数有矛盾,则不能算小.
-
题解:用\(pair\)来记录序列中元素的位置和大小,将他们升序排序,对于每对矛盾的位置,只记录\(a[u]>a[v]\)的情况,小于等于的情况没必要考虑,然后我们遍历排序后的序列,二分查找第一个大于等于它的位置,然后减去比它小的矛盾的点的个数即为答案.时间复杂度为\(O(n*logn)\)
-
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <vector> #include <map> #include <set> #include <unordered_set> #include <unordered_map> #define ll long long #define fi first #define se second #define pb push_back #define me memset const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<long,long> PLL; int n,k; int u,v; int r[N]; int ans[N]; vector<PII> A; vector<int> V[N]; bool cmp(PII a,PII b){ if(a.se!=b.se) return a.se<b.se; if(a.se==b.se) return a.fi<b.fi; } int main() { ios::sync_with_stdio(false);cin.tie(0); cin>>n>>k; for(int i=0;i<n;++i){ cin>>r[i]; A.pb({i,r[i]}); } for(int i=1;i<=k;++i){ cin>>u>>v; if(A[u-1].se>A[v-1].se) V[u-1].pb(v-1); else if(A[v-1].se>A[u-1].se) V[v-1].pb(u-1); } sort(A.begin(),A.end(),cmp); sort(r,r+n); for(int i=1;i<n;++i){ int pos=lower_bound(r,r+n,r[i])-r; int cnt=V[A[i].fi].size(); ans[A[i].fi]=max(0,pos-cnt); } for(int i=0;i<n;++i) printf("%d ",ans[i]); return 0; }