一个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
孔炤
(题目提供者)
首先我们需要对每个限制点进行不断更新,当每个限制点都达到他们最大可能的值后进行扫描即可。
有两种情况需要更新:
令 H = ti[i+1] - ti[i] ; D = x[i+1] - x[i];
1》 H >=0 且 H > D 时, 需要将 ti[i+1] 降至 ti[i] + D ;
2》 H < 0 且 -H > D 时,需要将 ti[i] 降至 ti[i+1] + D ; --- 此时 前面 的 ti值改变了,所以 需要从头开始更新。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
int x,y;
}pp[60];
bool cmp(node x, node y)
{
return x.x<y.x;
}
int gogo(int a,int b,int c)
{
a+=c;
b-=c;
b/=2;
a+=b;
return a;
}
void slove()
{
int n,m;
cin>>n>>m;
for (int i=1;i<=m;i++)
cin>>pp[i].x>>pp[i].y;
pp[0].x=1;pp[0].y=0;
pp[m+1].x=n;pp[m+1].y=n-1;
sort(pp,pp+m+2,cmp);
for (int i=0;i<=m;i++)
pp[i].y=min(pp[i].y,pp[i].x-1);
bool fafe=true;
int wx=1,wy=0,zx,zy,c,d,ans=0;
while (fafe)
{
fafe=false;
for (int i=1;i<=m+1;i++)
{
zx=pp[i-1].x;zy=pp[i-1].y;
wx=pp[i].x;wy=pp[i].y;
c=wx-zx;
d=wy-zy;
if (d>c)
{
pp[i].y=pp[i-1].y+c;
}
else if (d<-c)
{
pp[i-1].y=pp[i].y+c;
fafe=true;
break;
}
}
}
for (int i=1;i<=m+1;i++)
{
zx=pp[i-1].x;zy=pp[i-1].y;
wx=pp[i].x;wy=pp[i].y;
c=wx-zx;
d=wy-zy;
if (d>=0)
{
ans=max(ans,gogo(zy,c,d));
}
else
ans=max(ans,gogo(wy,c,-d));
}
cout<<ans<<endl;
}
int main()
{
int t;
cin>>t;
while (t--)
slove();
return 0;
}