5015. 决斗

题目大意

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

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

Data Constraint
n5×105

题解

Ri 表示一开始分配的编号小于等于 i 的数量。可以证明必定存在一个位置满足所有的精灵都不会跨过这个位置。即对于一个位置m RiR(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 + 10

vector < 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 ;
}

以上.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值