NOIP提高组--选择客栈

我看到有人用线段树来写而且想法和我的差不多,但是代码有一点复杂,所以我就贴一下我的做法。


思路

首先一定知道纯暴力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 ;
}

猜你喜欢

转载自www.cnblogs.com/chhokmah/p/10354168.html