洛谷 2879 & poj 3263 Tallest Cow 题解(思维,前缀和)

13 篇文章 0 订阅

原题链接:
poj
洛谷

题意简述

有一个序列,不确定,给定其长度 n ( &lt; = 1 e 4 ) n(&lt;=1e4) n(<=1e4),以及其中最大的数。这个最大的数在点 k ( 1 &lt; = k &lt; = n ) k(1&lt;=k&lt;=n) k(1<=k<=n),高为 h ( &lt; = 1 e 6 ) h(&lt;=1e6) h(<=1e6),以及 r r r个关系。每个关系是这样表示的:
两个 ( a , b ) (a,b) (a,b):第 a a a &lt; = &lt;= <= b b b个,并且 [ a + 1 , b − 1 ] [a+1,b-1] [a+1,b1]中都严格比 a a a小(没有等于的)。
(注意是 &lt; = &lt;= <=,洛谷上面有误,看英文珂知)

请最大化序列中的每个数,输出这个最大的序列。

思路

我们想想,如果没有限制,肯定就每个都 h h h了。但是为什么不行呢?因为有限制。

那么,一对限制 ( a , b ) (a,b) (a,b)出来之后,最优策略是什么呢?很明显,就是把 [ a + 1 , b − 1 ] [a+1,b-1] [a+1,b1]中的数都 − 1 -1 1
那么两个呢?三个呢?四个呢?。。。。
经过更深入的思考,我们发现,我们只要重叠那个区间减一的操作即珂。就是这个序列一开始都是 h h h,然后对于一个 ( a , b ) (a,b) (a,b),我们在 ( a + 1 , b − 1 ) (a+1,b-1) (a+1,b1)内减一,然后输出序列即珂。

那么我们如何维护呢?线段树和树状数组自然是珂以做的,但是有更简单的方法。对于这个题来说,差分是个好办法。然后最后求前缀和,加上 h h h,即珂。
(有一个细节注意,就是这个题里面相同的 ( a , b ) (a,b) (a,b)会出现很多次,要用一个 m a p map map判重。所以这就活活给时间复杂度多了一个 l o g log log。)

代码:

#include<bits/stdc++.h>
using namespace std;
namespace Flandle_Scarlet
{
    #define N 200100
    map<pair<int,int>,bool> vis;
    int n,id,h,r;
    void R1(int &x)
    {
        x=0;char c=getchar();int f=1;
        while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        x=(f==1)?x:-x;
    }
    void Input()
    {
        R1(n),R1(id),R1(h),R1(r);
    }
    int d[N];
    void Soviet()
    {
        for(int i=1;i<=r;++i)
        {
            int a,b;R1(a),R1(b);
            if (a>b) swap(a,b);
            if (vis[make_pair(a,b)]) continue;
            d[a+1]--;
            d[b]++;//[a+1,b-1]内减一
            vis[make_pair(a,b)]=1;
        }
        for(int i=1;i<=n;++i)
        {
            d[i]+=d[i-1];//原地变前缀和
            printf("%d\n",d[i]+h);//加上h
        }
    }
    void IsMyWife()
    {
        if (0)
        {
            freopen("","r",stdin);
            freopen("","w",stdout);
        }
        Input();
        Soviet();
    }
};
int main()
{
    Flandle_Scarlet::IsMyWife();
    return 0;
}

回到总题解界面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值