Codeforces1545D AquaMoon and Wrong Coordinate
题意
有(m)个人以恒定的速度大小(v_i)与方向在数轴上准备向右行走,已知包括初始时刻((t=0))在内的连续(k)个时刻(均为整数)所有人的位置(每次都乱序给出),并且其中有一个时刻某个人的位置被修改过,请找处被修改的时刻以及被修改的人的初始位置。((5leq mleq 1000,7leq kleq1000,v_ileq1000,x_{ij}leq10^6))
题解
由于所有人速度恒定,容易想到在没有值被修改的情况下相邻两时刻的(sum x_i)之差是恒定的,为(sum v_i),因此容易求出是在哪个时刻值被修改了并且能求出比修改前的值增大了或减少了多少。下面考虑如何定位是哪个人被修改了。
记(g_k)为第(k)天的(sum x_i^2),(X_i)为每个人的初始位置,(v_i)为每个人的速度,由于(g_k=sum(X_i+kv_i)^2),(g_{k-1}=sum(X_i+kv_i-v_i)^2),(g_{k+1}=sum(X_i+kv_i+v_i)^2),所以(g_{k+1}+g_{k-1}-2g_k=2sum v_i^2),由于(mgeq 5),故一定能找出没有被修改过的连续的三天,于是能求出正常的(sum v_i^2),然后直接枚举是哪个人被修改了判断(sum v_i^2)即可。
#include <bits/stdc++.h>
#define pb(x) emplace_back(x)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=2e5+100,INF=1<<30;
const ll M=1e9+7;
int m,k;
ll f[1004][1004],s[1004],g[1004];
map<ll,int> mp;
void f1(){
int p1=0,p2=0;
ll res=0,nb=0;
scanf("%d%d",&m,&k);
for(int i=1;i<=k;i++){
for(int j=1;j<=m;j++){
scanf("%lld",&f[i][j]);
s[i]+=f[i][j];
g[i]+=f[i][j]*f[i][j];
}
}
for(int i=2;i<=m;i++){
ll na=s[i]-s[i-1];
if(!mp.count(na)){
mp[na]=1;
}
else{
++mp[na];
}
}
for(int i=2;i<m;i++){
if(mp[s[i]-s[i-1]]==1&&mp[s[i+1]-s[i]]==1){
p1=i;
nb=(s[i]-s[i-1])-(s[i+1]-s[i]);
nb/=2;
break;
}
}
if(p1==0){
if(mp[s[2]-s[1]]==1){
p1=1;
nb=s[3]-s[2]-(s[2]-s[1]);
}
else {
p1=m;
nb=s[m]-s[m-1]-(s[m-1]-s[m-2]);
}
}
p2=(p1<=3?5:2);
res=g[p2+1]+g[p2-1]-2ll*g[p2];
int ans=0;
ll tmp=g[p1];
for(int i=1;i<=m;i++){
int nc=f[p1][i]-nb;
g[p1]=g[p1]-f[p1][i]*f[p1][i]+1ll*nc*nc;
int p3=0;
if(p1==1)p3=2;
else if(p1==m)p3=m-1;
else p3=p1;
if(g[p3+1]+g[p3-1]-2ll*g[p3]==res){
ans=nc;break;
}
g[p1]=tmp;
}
printf("%d %d",p1-1,ans);
fflush(stdout);
}
int main(){
//pre();
//int t;scanf("%d",&t);
//while(t--)
f1();
return 0;
}
/*
1
5
6 9 1 9 6
*/