一个N长的数组s[](注意这里的数组初始下标设为1,而不是0,即N个元素为s[1],s[2],...,s[N]),满足以下性质:
1)每个元素都是非负的整数,且s[1]=0;
2)任意两个相邻元素差值的绝对值不大于1,即| s[i]-s[i+1] |<=1;
3)对于部分特殊点xi,要求s[xi]<=ti(这样的特殊点一共M个);
问在以上约束下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
两次for循环。
首先第一次,正着来,从i=1开始,不停地ans++,记录到达这个点最大的就是ans值.如果当前点有限制,且ans大于限制了,让ans=限制值,也就是最大值。这样扫完答案是不正确的,因为我们只扫了向右走的,我们保证i到i+1满足条件了,但是不能保证i+1到i满足条件。因为存在limt的原因,我们可能5后面直接变成1了,这样是不正确的。我们需要反向来一遍。求每一项的最小值的最大值。
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include<algorithm> #include<stack> using namespace std; int limit[110000]; int l[110000]; int r[110000]; int n,m; int main() { int t,a,b; scanf("%d",&t); while(t--) { memset(limit,-1,sizeof(limit)); memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); cin>>n>>m; while(m--) { cin>>a>>b; limit[a]=b; } limit[1]=0; int ans=0; for(int i=1;i<=n;i++) { ans++; if(ans>limit[i]&&limit[i]!=-1) { ans=limit[i]; } l[i]=ans; } ans=n; for(int i=n;i>=1;i--) { ans++; if(ans>limit[i]&&limit[i]!=-1) { ans=limit[i]; } r[i]=ans; } ans=-1; for(int i=1;i<=n;i++) { ans=max(ans,min(l[i],r[i])); } cout<<ans<<endl; } }