链接:https://vjudge.net/problem/CodeForces-375D#author=634579757
题意:n头牛站一排,两头牛能相互看见,当且仅当它们中间的牛的身高都比它们矮。已知它们中最高的牛的身高是H,并且她是第P头牛,还知道M对关系,每一对关系都指明两头牛Ai和Bi可以相互看见。求每头牛的身高最大可能是多少?
思路:可以用一个数组height表示各头牛的身高,但由于题目给的M个关系只是相对身高关系,所以可以用这个数组表示各个牛的身高的相对关系,最后可以直接已知的那头最高的牛以及它与其他牛的相对身高关系,得出其他牛的身高。
既然height数组表示的是相对身高,那么可以初始化0,然后对于每一个关系,指明Ai和Bi可以相互看见,就把height[Ai+1]~height[Bi-1]的数减去1。为什么是减去1呢? 因为题目要求的是可能的最大身高。最终,其他的牛与最高的那头牛的身高差距就体现在数组height中,换言之,最后第i头牛的身高就等于H+height[i]。
算法实现:
暴力:对于每个关系,都把Ai+1到Bi-1之间的数减去1,这样算法复杂度将是O(MN),复杂度过高。
前缀和思想:额外开一个help数组,对于每对Ai和Bi,也就是Ai+1到Bi-1之间的数都减去1,可以令help[Ai+1]减去1,然后令help[Bi]加上1,这样处理完之后,height[i]就是help的前i个数之和,也就是前缀和。这样的意思是:“减去1”的影响从Ai+1开始,持续到Bi-1,在Bi结束。这个算法把对一个区间的修改操作转化为仅仅对左右两个端点的修改操作,再通过前缀和得到原问题的解。复杂度为O(M+N)。这种思想很常用。
代码技巧:
①本题有一个坑,就是同一个关系(Ai,Bi)可能被输入多次,可重复的输入对于本题来说,是没有意义的,所有要对每一个关系判重。由于这是一组关系,是二元的,无法简单的通过vis[]数组实现,所以可以通过map<pair<int,int> bool> exist;实现。
if(exist[make_pair(a,b)])
continue;
exist[make_pair<a,b>] = true; //标志<a,b>已经出现过
代码:
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define Fin freopen("in.txt","r",stdin)
#define Fout freopen("out.txt","w",stdout)
#define Case(T) int T;for(scanf("%d",&T);T--;)
#define fo(i,a,b) for(int i = a; i < b; ++i)
#define fd(i,a,b) for(int i = a; i >= b; --i)
#define me(a,b) memset(a,b,sizeof(a))
#define fi(a,n,val) fill(a,a+n,val)
#define Scand(n) scanf("%d",&n)
#define Scans(s) scanf("%s",s)
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b ? gcd(b,a%b): a; }
const int maxn = 1e4 + 50;
const int INF = 0xffffff;
#ifndef ONLINE_JUDGE
#endif // ONLINE_JUDGE
int n,I,h,r;
int help[maxn], height[maxn];
map<pair<int, int>, bool> exist;
int main()
{
#ifndef ONLINE_JUDGE
//Fin;
#endif // ONLINE_JUDGE
while(scanf("%d%d%d%d",&n,&I,&h,&r) == 4){
fi(help, maxn-5, 0); fi(height, maxn-5, 0);
for(int i = 0; i < r; ++i){
int a,b;
scanf("%d%d",&a,&b);
if(a > b) swap(a, b);
if(exist[make_pair(a, b)])
continue;
help[a+1]--; help[b]++;
exist[make_pair(a, b)] = true;
}
for(int i = 1; i <= n; ++i){
height[i] = height[i-1]+help[i];
}
int changee = h-height[I];
for(int i = 1; i <= n; ++i){
printf("%d",height[i]+changee);
if(i != n)
printf("\n");
}
}
return 0;
}