【题 解 P5186 [COCI 2010] yard】

Topic Link

Solution [COCI 2010] FENCE

There was a platoon leader \ (n \) fence, you can be a long as \ (k \) fence staining, but can not exceed the height of the shortest Flanagan Asked less than the minimum brush area, and in this context the number of dyeing

analysis:

Since the minimum asked not brush the area, we can consider the limit, that is, the length of each segment \ (k \) fence brush again , if this were not brush it is not a

We define \ (mi [i] \) represents the point at the left end of the brush \ (I \) , the maximum distance can be up brush, set the original array as \ (Val \)

显然\(mi[i] = min\{val[j] \quad | \quad i \leq n - k + 1,i \leq j \leq i + k - 1\}\)

Because the brush must touch the fence, so there is a limit brush left point

We then set \ (mx [i] \) represents \ (I \) root barrier can brush up in the limit of the maximum distance

\(mx[i] = max\{mi[j] \quad | \quad max(1,i - k + 1) \leq j \leq i\}\)

Brush less then the minimum area of ​​$ ans1 = \ sum_ {i = 1} ^ {n} {val [i] -mx [i]} $

Above can be used in a monotone queue (O (n) \) \ within the time out process

For less than the least number of brush, we can consider greedy handle, see the code

#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 100;
int val[maxn],q[maxn],mi[maxn],mx[maxn],n,k;
ll ans1,ans2;//注意开long long
inline void init(){//单调队列预处理
    int head = 0,tail = 0;
    for(int i = 1;i < k;i++){
        while(head <= tail && val[q[tail]] >= val[i])tail--;
        q[++tail] = i;
    }
    for(int i = k;i <= n;i++){
        while(head <= tail && val[q[tail]] >= val[i])tail--;
        q[++tail] = i;
        while(head <= tail && q[head] <= i - k)head++;
        mi[i - k + 1] = val[q[head]];
    }
    head = 0,tail = 0;
    for(int i = 1;i < k;i++){
        while(head <= tail && mi[q[tail]] <= mi[i])tail--;
        q[++tail] = i;
        mx[i] = mi[q[head]];
        ans1 -= mx[i];
    }
    for(int i = k;i <= n;i++){
        while(head <= tail && mi[q[tail]] <= mi[i])tail--;
        q[++tail] = i;
        while(head <= tail && q[head] <= i - k)head++;
        mx[i] = mi[q[head]];
        ans1 -= mx[i];
    }
}
int main(){
    scanf("%d %d",&n,&k);
    for(int i = 1;i <= n;i++)scanf("%d",val + i),ans1 += val[i];
    init();
    printf("%lld\n",ans1);
    int v = -1,rt = -1;//v表示当前往上刷的最远距离,rt表示这段的右端点
    for(int i = 1;i <= n;i++)
        if(mx[i] != v || rt < i){//如果刷不完i这个位置或者刷不到i这个位置
            ans2++;
            v = mx[i];
            rt = i + k - 1;
        }
    printf("%lld\n",ans2);
    return 0;
}

Guess you like

Origin www.cnblogs.com/colazcy/p/11515165.html