5015. 决斗

来源:互联网 发布:nginx 反向代理403 编辑:程序博客网 时间:2024/04/29 17:32

题目大意

敌人有n个侏儒排成一个环,自己有n个精灵,每个侏儒和精灵都有一个力量值。每个精灵都有一个侏儒和他配对。
精灵依次进入和侏儒决斗,如果他配对的侏儒已经有对手,就顺势针找下一个。

找到一种安排顺序,求最多能赢多少局。

Data Constraint
n5×105

题解

Ri表示一开始分配的编号小于等于i的数量。可以证明必定存在一个位置满足所有的精灵都不会跨过这个位置。即对于一个位置mRiR(m1)+i(m1)<0恒成立。那么m显然Rm1(m1)最小。
然后从m这个位置断开环,贪心的放,用一个set维护。

时间复杂度:O(nlogn)

SRC

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<set>using namespace std ;#define N 500000 + 10vector < int > B[N] ;set < int > Q ;int R[N] ;int A[N] , P[N] , V[N] ;int n , ans ;int main() {    freopen( "fight.in" , "r" , stdin ) ;    freopen( "fight.out" , "w" , stdout ) ;    scanf( "%d" , &n ) ;    for (int i = 1 ; i <= n ; i ++ ) {        scanf( "%d" , &A[i] ) ;        B[A[i]].push_back(i) ;        R[A[i]] ++ ;    }    for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &P[i] ) ;    for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &V[i] ) ;    int wz = 0 , Minv = 0x7FFFFFFF ;    for (int i = 1 ; i <= n ; i ++ ) {        R[i] += R[i-1] ;        if ( R[i] - i < Minv ) {            Minv = R[i] - i ;            wz = i ;        } else if ( R[i] - i == Minv && B[i].size() > 0 ) wz = i ;    }    for (int i = wz % n + 1 ; ; i = (i % n) + 1 ) {        for (int j = 0 ; j < (signed)B[i].size() ; j ++ ) {            Q.insert( V[B[i][j]] ) ;        }        if ( *Q.rbegin() < P[i] ) Q.erase(Q.begin()) ;        else {            ans ++ ;            Q.erase( Q.upper_bound( P[i] ) ) ;        }        if ( i % n + 1 == wz % n + 1 ) break ;    }    printf( "%d\n" , ans ) ;    return 0 ;}

以上.

1 0
原创粉丝点击