poj3268 Tallest Cow (暴力or差分+前缀和)

Tallest Cow

poj3263

问题描述

FJ的N(1≤N≤10000)头奶牛1…N 在排队。每头牛的高度都是正整数(这是一个小秘密)。只告诉您最高的牛的高度H(1≤H≤1,000,000)以及该牛的索引I。
FJ以“cow 17 see cow 34”的形式列出了R(0≤R≤10000)行。这意味着奶牛34至少和奶牛17一样高,而且每一头17到34岁的奶牛的高度都严格小于奶牛17的高度。
从1…N,确定它的最大可能高度,这样给出的所有信息都是正确的。它保证有可能满足所有的约束条件。

输入

第1行:四个空格分隔的整数:N、I、H和R
行2 . .R+1:两个不同的空格分隔整数A和B(1≤A, B≤N),表示奶牛A可以看到奶牛B。

输出

行1 . .N:第i行包含奶牛i的最大可能高度。

Sample Input

9 3 5 5
1 3
5 3
4 3
3 7
9 8

Sample Output

5
4
5
3
4
4
5
5
5

分析:

如果a和b可以相互看见,那么他们中间的牛肯定比他们矮。
为了保证牛的身高最高,只让a和b之间的牛的高度-1。
定义数组数组d[]表示牛的相对高度,起初初始化为0.
当给出a和b能互相看见的时候,把a于b之间牛的相对高度-1.
因为最高的牛相对高度是0,所以最后每只牛的相对高度是d[i]+H.

[l,r]区间操作有两种做法,一种是暴力一种是差分前缀和。亲测两种都能过。

这题还有两个坑点,一个是牛a和b的数字大小不是确定的a<b因此要先判断大小再进行区间修改。
另一个是题目可能会给相同的相对关系,因此要标记防止重复修改。

暴力:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#include<sstream>
#include<memory>
#include<utility>
#include<functional>
#include<iterator>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=1e5;
int N,I,H,R;
int main(){
    while(cin>>N>>I>>H>>R){
        int a[maxm]={0};
        map<pair<int,int> ,int>mark;
        for(int i=1;i<=R;i++){
            int aa,bb;
            cin>>aa>>bb;
            if(aa>bb)swap(aa,bb);
            if(mark[make_pair(aa,bb)]){
                continue;
            }
            mark[make_pair(aa,bb)]++;
            for(int j=aa+1;j<=bb-1;j++){
                a[j]--;
            }
        }
        for(int i=1;i<=N;i++){
            cout<<a[i]+H<<endl;
        }
    }
    return 0;
}
不暴力:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#include<sstream>
#include<memory>
#include<utility>
#include<functional>
#include<iterator>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=1e5;
int N,I,H,R;
int main(){
    while(cin>>N>>I>>H>>R){
        int a[maxm]={0};
        int d[maxm]={0};
        map<pair<int,int> ,int>mark;
        for(int i=1;i<=R;i++){
            int aa,bb;
            cin>>aa>>bb;
            if(aa>bb)swap(aa,bb);
            if(mark[make_pair(aa,bb)]){
                continue;
            }
            mark[make_pair(aa,bb)]++;
            d[aa+1]--;
            d[bb]++;
        }
        for(int i=1;i<=N;i++){
            a[i]=a[i-1]+d[i];
        }
        for(int i=1;i<=N;i++){
            cout<<a[i]+H<<endl;
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值