1. 程式人生 > >洛谷 P2205 [USACO13JAN]畫柵欄Painting the Fence

洛谷 P2205 [USACO13JAN]畫柵欄Painting the Fence

%d lan rest target write call logic www. 離散

P2205 [USACO13JAN]畫柵欄Painting the Fence

題目描述

Farmer John has devised a brilliant method to paint the long fence next to his barn (think of the fence as a one-dimensional number line). He simply attaches a paint brush to his favorite cow Bessie, and then retires to drink a cold glass of water as Bessie walks back and forth across the fence, applying paint to any segment of the fence that she walks past.

Bessie starts at position 0 on the fence and follows a sequence of N moves (1 <= N <= 100,000). Example moves might be "10 L", meaning Bessie moves 10 units to the left, or "15 R", meaning Bessie moves 15 units to the right. Given a list of all of Bessie‘s moves, FJ would like to know what area of the fence gets painted with at least K coats of paint. Bessie will move at most 1,000,000,000 units away from the origin during her walk.

Farmer John 想出了一個給牛棚旁的長圍墻塗色的好方法。(為了簡單起見,我們把圍墻看做一維的數軸,每一個單位長度代表一塊柵欄)他只是簡單的把刷子蘸滿顏料,系在他最喜歡的奶牛Bessie上,然後讓Bessie來回地經過圍墻,自己則在一旁喝一杯冰鎮的涼水。(……-_-|||) Bessie 經過的所有圍墻都會被塗上一層顏料。Bessie從圍墻上的位置0出發,並將會進行N次移動(1 <= N <= 100,000)。比如說,“10 L”的意思就是Bessie向左移動了10個單位。再比如說“15 R”的意思就是Bessie向右移動了15個單位。給出一系列Bessie移動的清單。FJ 想知道有多少塊柵欄塗上了至少K層塗料。註意:Bessie最多會移動到離原點1,000,000,000單位遠的地方。

輸入輸出格式

輸入格式:

  • 第1行: 兩個整數: N K

  • 第2...N+1 行: 每一行都描述了Bessie的一次移動。 (比如說 “15 L")

輸出格式:

  • 一個整數:被至少塗上K層塗料的柵欄數

(註意:輸出的最後一定要輸出換行符!否則會WA)

輸入輸出樣例

輸入樣例#1:
6 2 
2 R 
6 L 
1 R 
8 L 
1 R 
2 R 
輸出樣例#1:
6

說明

PS1:來源:usaco jan silver P01 想看原題的請戳http://www.usaco.org/index.php?page=viewproblem2&cpid=226)

PS2:測試數據也可以在在http://www.usaco.org/index.php?page=jan13problems上下載,還可以看到題解(不過是英文的:-D)

PS3:如果有翻譯的問題或題目的不理解,可以在問答後面留言的說。

思路:

這是當年的官方思路:

If we knew the area Bessie was going to paint were small, this would be easy; we could just explicitly keep track of how many coats of paint each unit of fence had. Unfortunately, we don‘t.

But...Bessie only stops on at most 100,001 different points (one per move). So these are the only "interesting coordinates". In particular, any two points between two "interesting coordinates" will have the same number of coats of paint (this idea is a generally useful trick called "coordinate compression", and it‘s worth knowing). So it‘s enough to keep track of the number of coats of paint along each of these 100,002 segments.

This still might not be fast enough; each move could cover all 100,002 segments, so this algorithm still looks quadratic. So we can apply another useful trick, which is just keeping track of the deltas introduced by each of Bessie‘s moves. Each of Bessie‘s moves is a segment (on our coordinate-compressed line), and at the beginning of the segment we write down "+1 coats of paint" and at the end of the segment we write down "-1 coats of paint". Then if we scan from left to right, we can add up the deltas as we go, and keep track of the number of coats on each segment.

This gives an O(n lg n) solution (to "scan from left to right", we need to sort the segments). It was a bit of a winding logical path to get here, so the final solution may not be quite clear. Take a look at Travis Hance‘s solution, which presents the idea quite elegantly: (and remember coordinate compression and deltas-for-segments for later!)

看不懂是吧,我英語不好,也看不懂。所以用了差分+離散化搞了一下。

#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
map<int,int>F;
int q[300000],top;
int n,m,now,ans;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        char c;int x;
        scanf("%d",&x);
        cin>>c;
        if(c==R){
            q[++top]=now;
            F[q[top]]++;
            q[++top]=now+x;
            F[q[top]]--;
            now+=x;
        }else{
            q[++top]=now-x;
            F[q[top]]++;
            q[++top]=now;
            F[q[top]]--;
            now-=x;
        }
    }
    sort(q+1,q+top+1);
    now=F[q[1]];
    for(int i=2;i<=top;i++)
        if(q[i]!=q[i-1]){
            if(now>=m)    ans+=q[i]-q[i-1];
            now+=F[q[i]];
        }
    printf("%d",ans);
}

洛谷 P2205 [USACO13JAN]畫柵欄Painting the Fence