1. 程式人生 > >[BZOJ5139][Usaco2017 Dec]Greedy Gift Takers 權值線段樹

[BZOJ5139][Usaco2017 Dec]Greedy Gift Takers 權值線段樹

turned set ble however may lin \n can bsp

Description

Farmer John‘s nemesis, Farmer Nhoj, has NN cows (1≤N≤10^5), conveniently numbered 1…N. They have unexpectedly turned up at Farmer John‘s farm, so the unfailingly polite Farmer John is attempting to give them gifts.To this end, Farmer John has brought out his infinite supply of gifts, and Nhoj‘s c ows have queued up in front of him, with cow 11 at the head of the queue and cow N at the tail. Farm er John was expecting that at every timestep, the cow at the head of the queue would take a gift fro m Farmer John and go to the tail of the queue. However, he has just realized that Nhoj‘s cows are no t that polite! After receiving her gift, each cow may not go to the tail of the queue, but rather ma y cut some number of cows at the tail, and insert herself in front of them. Specifically, cow ii wil l always cut exactly cici cows (0≤ci≤N-1).Farmer John knows that some cows might receive multiple gifts; as he has an infinite supply, this does not worry him. But he is worried that some cows might become unhappy if they do not get any gifts.Help Farmer John find the number of cows who never rece ive any gifts, no matter how many gifts are handed out. 有 N (1 <= N <= 10^5)頭牛按順序排成一列,編號從1到N,1 號牛在隊頭,N 號牛在隊尾。每次位於隊頭的牛 i 拿到一個禮物,然後插入到從隊尾數 c_i 頭牛之前的位置。舉個栗子: 初始隊列 1 2 3 4 5, c_1 = 2,c_2 = 3,則第一次操作後的序列為 2 3 4 1 5,第二次操作後的序列為 3 2 4 1 5 。重復無限次操作,求最後有幾頭牛 拿不到禮物。

Input

The first line contains a single integer, N. The second line contains N space-separated integers c1,c2,…,cN

Output

Please output the number of cows who cannot receive any gifts.

Sample Input

3
1 2 0

Sample Output

1

HINT

Source

Platinum

Solution

做法:權值線段樹

後面的牛不會領到禮物當且僅當前面形成了循環節

所以找出最小的循環節就是答案了

設$a_i = n - c_i $,$x=max(b_i)$($b_i$在循環節中),形成循環節的條件就是牛的數量大於等於$x$(這個在紙上畫畫圖就出來了)

枚舉這個$x$,然後在$b_i<=x$的$b_i$中找第$x$小的,這個操作可以用權值線段樹維護

#include <bits/stdc++.h>

using namespace std ;

#define lc ( rt << 1 | 1 )
#define rc ( rt << 1 )
const
int N = 1e5 + 10 ; int n ; int c[ N ] , t[ N << 2 ] ; int ans ; vector < int > vt[ N ] ; void add( int l , int r , int rt , int x ) { t[ rt ] ++ ; int mid = ( l + r ) >> 1 ; if( l == r ) return ; if( x <= mid ) add( l , mid , lc , x ) ; else add( mid + 1 , r , rc , x ) ; } int query( int l , int r , int rt , int x ) { if( l == r ) return l ; int mid = ( l + r ) >> 1 ; if( t[ lc ] >= x ) return query( l , mid , lc , x ) ; else return query( mid + 1 , r , rc , x - t[ lc ] ) ; } int main() { scanf( "%d" , &n ) ; for( int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &c[ i ] ) , vt[ n - c[ i ] ].push_back( i ) ; ans = n ; for( int i = 1 ; i <= n ; i ++ ) { for( int j = 0 , len = vt[ i ].size() ; j < len ; j ++ ) add( 1 , n , 1 , vt[ i ][ j ] ) ; if( t[ 1 ] >= i ) ans = min( ans , query( 1 , n , 1 , i ) ) ; } printf( "%d\n" , n - ans ) ; return 0 ; }

[BZOJ5139][Usaco2017 Dec]Greedy Gift Takers 權值線段樹