NOIP提高組--選擇客棧
阿新 • • 發佈:2019-02-07
如果 urn 思考 代碼 之前 ret space 所有 ()
我看到有人用線段樹來寫而且想法和我的差不多,但是代碼有一點復雜,所以我就貼一下我的做法。
思路
首先一定知道純暴力50分差不多了,所以看到k非常的小,那麽就從k入手。
不知道有沒有人和我一樣是先枚舉顏色的,那麽我們來思考一下,對於每個相同顏色的客站之間[l,r],如果當前區間不能找到一個合理的咖啡廳,那麽一定會影響到和他連在一起的下一個不能找到咖啡廳的區間。那麽我們就將這個標記放在r這個節點上,那麽第一個節點我們就當做是0。
說的形象一點,就是看這個節點能和前面多少個相同顏色的客棧組成合法的方案。
如果當前的區間是合法的,那麽前面的所有點都是可以和這個點組成方案。
算法實現
每一次算出這個客棧之前有多少個相同顏色的客棧,然後我們通過一個標記,表示在與這個區間相連接的前面幾個區間內有多少個不合法的區間,每一次算的時候我們就需要把這些點數減掉。
如果當前的區間是不合法的,那麽我們就需要將這個標記+1,否則就將這個標記設置成0。
代碼
# include <bits/stdc++.h> # define N 200005 # define Inf 0x3f3f3f3f using namespace std ; struct node { int c , v ; }a[N] ; int n , k , p , ans = 0 ; int main () { scanf( "%d%d%d" , &n , &k , &p ) ; for ( int i = 1 ; i <= n ; i ++ ) scanf( "%d%d" , &a[i].c , &a[i].v ) ; for ( int i = 0 ; i < k ; i ++ ) { int cnt = 0 , sub = Inf , tmp = 0 , re = 0 ; //re表示有多少連接的前區間不合法 for ( int j = 1 ; j <= n ; j ++ ) { sub = min ( a[j].v , sub ) ; if ( a[j].c == i ) { tmp += cnt ++ ; if ( sub > p ) tmp = max ( tmp - ++ re , 0 ) ; else re = 0 ; sub = a[j].v ; } } ans += tmp ; } printf( "%d\n" , ans ) ; return 0 ; }
NOIP提高組--選擇客棧