51NOD 1402 最大值

1402 最大值
题目来源: TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
收藏
关注
一个N长的数组s[](注意这里的数组初始下标设为1,而不是0,即N个元素为s[1],s[2],...,s[N]),满足以下性质:
1)每个元素都是非负的整数,且s[1]=02)任意两个相邻元素差值的绝对值不大于1,即| s[i]-s[i+1] |<=13)对于部分特殊点xi,要求s[xi]<=ti(这样的特殊点一共M个);
问在以上约束下s[]中的最大值最大可能是多少?
Input

多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
每组测试数据有相同的结构构成:
第一行两个整数N,M,表示s[]的长度与特殊点的个数,其中1<=N<=100000,0<=M<=50.
之后M行,每行两个整数xi与ti,其中1<=xi<=N,0<=ti<=100000,且xi以增序给出。

Output

每组数据一行输出,即数组的可能最大值。

Input示例

3
10 2
3 1
8 1
100000 0
2718 5
1 100000
30 100000
400 100000
1300 100000
2500 100000

Output示例

3
99999
2717

考虑让每个特殊点的值最大
不难发现 确定了特殊点的值 最大值就能在O(m)内找到
插入一个特殊值复杂度不超过O(m)
总体复杂度为O(m^2)

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<string>
#include<vector>
#include<deque>
#include<queue>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<time.h>
#include<math.h>
#include<list>
#include<cstring>
#include<fstream>
//#include<memory.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define INF 1000000007
#define pll pair<ll,ll>
#define pid pair<int,double>

vector<pii>vec;//记录特殊点上的值  first=下标 second=值

void add(int x,int t){//插入特殊点
    if(x==1)//下标为1 恒为0
        return;
    int prex=vec.back().first;//上一个特殊点
    int pret=vec.back().second;
    if(x>prex){
        if(abs(x-prex)>=abs(t-pret))
            vec.push_back({x,t});
        else{
            if(pret<t)//特殊点的最大值过大
                vec.push_back({x,x-prex+pret});
            else{//过小 需要把前面的特殊点的值减小
                vec.pop_back();//删掉前面的点
                add(prex,t+x-prex);//添加回一个适当小的
                vec.push_back({x,t});
            }
        }
    }
    else{
        if(t<pret){//下标和上一个点相同
            vec.pop_back();
            add(x,t);
        }
    }
}

int main()
{
    //freopen("/home/lu/文档/r.txt","r",stdin);
    //freopen("/home/lu/文档/w.txt","w",stdout);
    int T,n,m,x,t;
    cin>>T;
    while(T--){
        vec.clear();
        vec.push_back({1,0});
        cin>>n>>m;
        while(m--){
            cin>>x>>t;
            add(x,t);
        }
        int ans=0;
        for(int i=1;i<vec.size();++i){
            int x1=vec[i-1].first,x2=vec[i].first;
            int t1=vec[i-1].second,t2=vec[i].second;
            int tmp=abs(x2-x1)-1-abs(t1-t2);
            tmp=tmp%2+tmp/2;
            ans=max(ans,tmp+max(t1,t2));
        }
        ans=max(vec.back().second+n-vec.back().first,ans);
        cout<<ans<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值