原题链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1402
思路:借鉴了这篇博文http://blog.csdn.net/hnust_derker/article/details/52550426的思路和做法
从前往后扫如果没有限制则+1,有限制则取limit和当前值中的最小值, 再以相同方法从后往前扫,再重新扫一边求两次扫后结果的最小即可。
这个思路很棒啊,每次扫到有限制的点,就相当于从这个点重新出发,往左或往右递增,把从两端扫的结果一重合,互相约束,就能得到正确结果。
AC代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int MAXN=1e5+10; 6 const int INF=1e7+5; 7 int t[MAXN]; 8 int l[MAXN],r[MAXN]; 9 int main() 10 { 11 int T; 12 int n,m,x,p; 13 cin>>T; 14 15 while(T--) 16 { 17 scanf("%d %d", &n, &m); 18 memset(t, -1, sizeof(t)); 19 memset(l, 0, sizeof(l)); 20 memset(r, 0, sizeof(r)); 21 22 for(int i=1;i<=m;i++){ 23 scanf("%d %d", &p, &x); 24 t[p]=x; 25 } 26 t[1]=0; 27 int res1=0,res2=INF; 28 for(int i=1;i<=n;i++){ 29 res1++; 30 if(t[i]>=0) res1=min(res1, t[i]); 31 l[i]=res1; 32 } 33 for(int i=n;i>=1;i--){ 34 res2++; 35 if(t[i]>=0) res2=min(res2, t[i]); 36 r[i]=res2; 37 } 38 int res=0; 39 for(int i=1;i<=n;i++){ 40 res=max(res, min(l[i], r[i])); 41 } 42 printf("%d ", res); 43 } 44 return 0; 45 }