1. 程式人生 > >【P2879】 [USACO07JAN]區間統計Tallest Cow {前綴和,思維}

【P2879】 [USACO07JAN]區間統計Tallest Cow {前綴和,思維}

證明 pair 沒有 names 算法 int for 區間 algorithm

思路:

先初始化所有牛的身高為0。

對於每一個約束條件(a,b)我們將a+1 ~ b-1的牛的身高全部減一。

樸素的減是TLE的,所以我們維護一個前綴和數組d[]來搞,對於約束條件(a,b)我們將d[a+1]--,將d[b]++。

碎碎念:

這個思路很明白,但是為什麽是正確的(尤其是為什麽每次減一不會產生矛盾)?我把luogu的題解瀏覽了一遍也沒有看到證明。

所以我就自己證了一下。有兩種證明方法:

一是循環不變式(算法導論上有很漂亮的例子),證起來很清晰。

二是反證法:假設有一組約束條件必須減>=2才能夠滿足,可以導出矛盾。

這裏不展開證明,經過思考應當容易寫出。

code:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
using namespace std;

map<pair<int,int>,bool> existed;
int c[10010],d[10010];

int main(){
    int n,p,h,m;
    scanf("%d%d%d%d",&n,&p,&h,&m);
    for(int i = 1
;i <= m;++i){ int a,b; scanf("%d%d",&a,&b); if(a > b)std::swap(a,b); if(existed[make_pair(a,b)])continue; d[a+1]--,d[b]++; existed[make_pair(a,b)] = true; } for(int i = 1;i <= n;++i){ c[i] = c[i-1]+d[i]; printf(
"%d\n",h+c[i]); } return 0; }

【P2879】 [USACO07JAN]區間統計Tallest Cow {前綴和,思維}