一个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
思路:
一, 从前向后扫一遍,每次都取最大值,若超过限制,则取限制值。再从后向前同样扫一遍,那么数组的最大值 就为 max{下标 i 扫两次的最小值},因为两次遍历都是最大值,而这两个最大值中较小的那个是可以成立的。 时间复杂度为 O(T*n)
二,对于有限制的点分析:由于从前向后取最大值会有可能不能小于某一个限制点的限制值,因此可以从后向前进行处理,对于相邻限制两点,以限制值较低的那个点去限制那个限制值高的点的限制值,使其两点可以相互到达,即限制值较高的那个点以其限制值每次减一能够到达限制值较低的那个点。这样在从前向后取最大值时,不会出现大于限制值的情况。在每次取得限制点的最大值,同时保持 过程中的最大值即可,只要的时间复杂度为 O(T*M)
Code 1:
#include<iostream>
#include<cstring>
using namespace std;
const int MAX_N=100005;
int n,m,T;
int a1[MAX_N],a2[MAX_N];
int b[MAX_N];
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--){
for(int i=0;i<MAX_N;++i)
a1[i]=a2[i]=0,b[i]=-1;
cin>>n>>m;
int id,x;
for(int i=0;i<m;++i)
{
cin>>id>>x;
b[id]=x;
}
for(int i=2;i<=n;++i)
if(b[i]>=0) a1[i]=min(b[i],a1[i-1]+1);
else a1[i]=a1[i-1]+1;
a2[n+1]=a1[n];
for(int i=n;i>0;--i)
if(b[i]>=0) a2[i]=min(b[i],a2[i+1]+1);
else a2[i]=a2[i+1]+1;
int ans=0;
for(int i=1;i<=n;++i)
ans=max(ans,min(a1[i],a2[i]));
cout<<ans<<endl;
}
return 0;
}
#include<iostream>
using namespace std;
struct node{
int id;
int mx;
};
const int MAX_M=55;
int n,m,T;
node a[MAX_M];
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--){
cin>>n>>m;
for(int i=0;i<m;++i)
cin>>a[i].id>>a[i].mx;
for(int i=m-1;i>0;--i)
if(a[i].mx>a[i-1].mx){
a[i].mx=min(a[i].mx,a[i-1].mx+a[i].id-a[i-1].id);
}else a[i-1].mx=min(a[i-1].mx,a[i].mx+a[i].id-a[i-1].id);
int ans=0;
int h=0;
if(a[0].id<=a[0].mx) ans=max(ans,a[0].id-1);
else ans=max(ans,(a[0].id+a[0].mx-1)/2);
h=min(a[0].mx,a[0].id-1);
for(int i=1;i<m;++i)
if(h<a[i].mx){
if(h+a[i].id-a[i-1].id<a[i].mx) ans=max(ans,h+a[i].id-a[i-1].id);
else ans=max(ans,(a[i].id+a[i].mx+h-a[i-1].id)/2);
h=min(a[i].mx,h+a[i].id-a[i-1].id);
}else{
ans=max(ans,(a[i].id+a[i].mx+h-a[i-1].id)/2);
h=a[i].mx;
}
if(m) ans=max(ans,h+n-a[m-1].id);
else ans=max(ans,n-1);
cout<<ans<<endl;
}
return 0;
}