题目
Description
NN个精灵和NN个矮人正在举行摔跤大赛。NN个矮人顺时针依次站在一个圆周上。
第ii个精灵将要和第AiAi个矮人摔跤。然而,由于主办方的失误,AA中可能有相同的元素。精灵将按照一定的顺序入场。入场的xx号精灵将优先和AxAx号矮人摔跤,但如果当前矮人已经和其他精灵摔过跤了,xx号精灵将尝试和顺时针方向的下一个矮人摔跤,以此类推,直到找到一个还没有摔过跤的矮人。
ii号矮人的力量值为PiPi,ii号精灵的力量值为ViVi。所有的力量值两两不同。在摔跤时,力量值高的一方一定会获胜。精灵们想知道,如果妥善安排入场顺序,最多有多少精灵获胜?
Input format
第一行一个整数NN(1≤N≤5×105)1≤N≤5×105)。 第二行NN个整数,第ii个表示AiAi(1≤Ai≤N1≤Ai≤N)。 第三行NN个整数,第ii个表示PiPi(1≤Pi≤1091≤Pi≤109)。 第四行NN个整数,第ii个表示ViVi(1≤Ai≤1091≤Ai≤109)。
Output format
一行一个整数,表示精灵最多胜利的次数。
Sample input 1
3
2 3 3
4 1 10
2 7 3
Sample output 1
2
Sample input 2
4
3 1 3 3
5 8 7 10
4 1 2 6
Sample output 2
1
Sample input 3
3
1 2 3
8 4 3
9 2 6
Sample output 3
2
Constrains
本题采用子任务的方式评测。
子任务一(20pts20pts):保证Ai=1Ai=1。
子任务二(30pts30pts):保证N≤1000N≤1000。
子任务三(50pts50pts):没有额外限制。
思路
若有个,记。可以发现,。考虑的前缀和最小的位置,可以发现,不管顺序如何,一定没有精灵顺时针越过这个位置。于是环的问题就变成了序列的问题。我们可以对序列进行贪心:从后往前,对于每个精灵,如果它能赢以后的某个矮人,就让它对抗它能赢的最强的矮人,否则让它对抗最强的矮人。用set维护能力值,复杂度为。
代码
#include <set>
#include <cstdio>
#include <vector>
inline int rint () {
int x = 0, f = 1; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x * f;
}
template<typename Tp>
inline void wint ( Tp x ) {
if ( x < 0 ) putchar ( '-' ), x = ~ x + 1;
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
}
const int MAXN = 5e5;
int N, A[MAXN + 5], P[MAXN + 5], V[MAXN + 5];
std :: vector<int> val[MAXN + 5];
std :: set<int> st;
inline int nxt ( const int i ) { return i % N + 1; }
int main () {
N = rint ();
for ( int i = 1; i <= N; ++ i ) A[i] = rint ();
for ( int i = 1; i <= N; ++ i ) P[i] = rint ();
for ( int i = 1; i <= N; ++ i ) val[A[i]].push_back ( V[i] = rint () );
int p = -1, mns = N;
for ( int i = 1, s = 0; i <= N; ++ i ) {
s += int ( val[i].size () ) - 1;
if ( mns > s ) p = nxt ( i ), mns = s;
}
int ans = 0;
for ( int i = p, stp = N; stp --; i = nxt ( i ) ) {
for ( int ele: val[i] ) st.insert ( ele );
std :: set<int> :: iterator it ( st.lower_bound ( P[i] ) );
if ( it != st.end () ) ++ ans, st.erase ( it );
else st.erase ( st.begin () );
}
printf ( "%d\n", ans );
return 0;
}