51NOD 1402 最大值 By Assassin

来源:互联网 发布:二维数组去除重复 编辑:程序博客网 时间:2024/05/29 08:55

1402 最大值
题目来源: TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
收藏
关注
一个N长的数组s,满足以下性质:
1)每个元素都是非负的整数,且s[1]=0;
2)任意两个相邻元素差值的绝对值不大于1,即| s[i]-s[i+1] |<=1;
3)对于部分特殊点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

给大家分享一下这个题目。。。毙了狗真是弱在别人提示的情况下还Wa了好多次,好吧,进入正题!
这个需要注意什么,首先一个位置可以是多少受两边的特殊位置影响!但是我们注意!起点是固定的,那么我们从左向右先跑一下,能得到各个节点位置可以最大的值(残缺的),这时我们能知道最右边一个特殊位置的最大值,然后我们从右边的向左更新,取两次计算的最小值。
然后怎么办?算两个特殊点之间每一段可能的最大值!我是分了两种情况,
1.相邻的,需要特判一下 弱卡在这里
2.不相邻那么先对其,然后判断奇偶计算即可。
然后!别忘了特殊点是不是最好的?遍历一下
总共更新一下最大值即可

#include<bits/stdc++.h>#define input freopen("input.txt","r",stdin)using namespace std;int value[55][3];int main(){    input;    int t,n,m,i,j,k;    scanf("%d",&t);    value[0][0]=1;   //初始化第一个固定点s[1]=0;  value[0][]代表位置     value[0][1]=0;   //value[1][]代表最大限制     value[0][2]=0;   //value[2][]代表可以选的最大值     while(t--){        scanf("%d%d",&n,&m);        int t1,t2,num=1;        for(i=1;i<=m;i++){            scanf("%d%d",&t1,&t2);            if(t1==1)continue;  //多此一举了去重了一下             value[num][0]=t1;            value[num][1]=t2;            num++;        }        m=num-1;        for(i=1;i<=m;i++){   //这时起点是确定的 从1开始 ,即考虑左边的影响             if(value[i][0]-value[i-1][0]+value[i-1][2]<value[i][1]){                value[i][2]=value[i][0]-value[i-1][0]+value[i-1][2];            }            else{                value[i][2]=value[i][1];            }        }        for(i=m-1;i>=0;i--){     //这时终点是确定的 ,这次 右边的影响,需要更新要最小值             value[i][2]=min(value[i][2],value[i+1][2]+value[i+1][0]-value[i][0]);        }        int ans=0;        for(i=1;i<=m;i++){            //这个是个特别坑的特判,即相邻且只差1的情况!我就是坑死在这的             if(value[i][0]==value[i-1][0]+1&&abs(value[i][2]-value[i-1][2])){                ans=max(ans,max(value[i][2],value[i-1][2]));                continue;            }            int cha=value[i][0]-value[i-1][0]-1;  //其他的可以先对其,然后找更高的             cha=cha-abs(value[i][2]-value[i-1][2]);            int key=max(value[i-1][2],value[i][2])+cha/2;            if(cha%2) key++;            ans=max(ans,key);         }        for(i=1;i<=m;i++){  //更新最大位置在特殊点上             ans=max(ans,value[i][2]);        }        cout<<max(ans,value[m][2]+n-value[m][0])<<endl; //最后一段     }    return 0;}
0 0