给你一个等差数列,首项为
A
,公差为D
,项数为N
,问X
和这N
项中数字差的绝对值最小为多少
二分一下,找到离他最近的两项,求一个最小值就行
注意公差可能为负数,所以可以分情况讨论,或者可以将这
N
个数倒着看就成了公差为正数的一个等差数列注意,如果二分的后找到大于等于
x
的位置是第一项或者第n+1项,那答案就只由一个数决定,否则是取左右两个的最小值,要特判一下
#include
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 300000 + 50
ll n, a, d, x;
ll f(ll n){
return a + (n - 1) * d;
}
void work(){
cin >> x >> a >> d >> n;
ll l = 1, r = n;
while(l <= r){
ll mid = (l + r) / 2;
if(d >= 0){
if(f(mid) > x)r = mid - 1;
else if(f(mid) < x)l = mid + 1;
else {
cout << 0 << endl;
return;
}
}
else{
if(f(mid) < x)r = mid - 1;
else if(f(mid) > x)l = mid + 1;
else {
cout << 0 << endl;
return;
}
}
}
if(d >= 0){
ll id = l - 1;
if(!id)cout << a - x << endl;
else if(id == n)cout << x - f(n) << endl;
else{
cout << min(x - f(id), f(id + 1) - x) << endl;
}
}
else{
ll id = r + 1;
if(id == 1)cout << x - a << endl;
else if(id == n + 1)cout << f(n) - x << endl;
else{
cout << min(f(id - 1) - x, x - f(id)) << endl;
}
}
}
int main(){
io;
work();
return 0;
}
给你数列A,若干次询问,每次询问都是问一个数字
X
,你可以对数列中任意一个数进行若干次加一或减一的操作,问将数组A
的数字全部变成X
需要多少次操作
排序后维护一个前缀和,对于每个
X
,我们将数组分成都小于X的数和都大于等于X的数,分别对这两部分求答案,这只需要知道数字个数和数字和即可,所以要维护一个前缀和
#include
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 300000 + 50
ll n, m, k, x;
ll tr[MAX];
ll sum[MAX];
ll getsum(ll l, ll r){
return sum[r] - sum[l - 1];
}
void work(){
cin >> n >> m;
for(int i = 1; i <= n; ++i)cin >> tr[i];
sort(tr + 1, tr + 1 + n);
for(int i = 1; i <= n; ++i)sum[i] = sum[i - 1] + tr[i];
tr[n + 1] = 1e18;
for(int i = 1; i <= m; ++i){
cin >> x;
ll id = upper_bound(tr + 1, tr + 2 + n, x) - tr;
if(id == 1 || id == n + 1){
cout << abs(n * x - getsum(1, n)) << endl;
}
else{
cout << (id - 1) * x - getsum(1, id - 1) + getsum(id, n) - (n - id + 1) * x << endl;
}
}
}
int main(){
io;
work();
return 0;
}
给你
N-1
个数字S[i]
,以及M
个数字X[i]
,现在定义数组A
满足A[i] + A[i + 1] = S[i],i=1,2,...,N-1
,问当M个数字在数组A中出现次数最多的时候是多少个
不难发现,当
A[1]
固定以后,数组A
就固定了,所以我们要想办法把A[i]
用A[1]
表示出来
A[2] = S[1] - A[1]
A[3] = S[2] - A[2] = S[2] - S[1] + A[1]
A[4] = S[3] - A[3] = S[3] - S[2] + S[1] - A[1]
我们设
B[i] = S[i] - B[i], i >= 2, B[1] = 0
所以 A [ i ] = B [ i ] + ( − 1 ) i + 1 ∗ A [ 1 ] A[i] = B[i] + (-1)^{i+1}*A[1] A[i]=B[i]+(−1)i+1∗A[1]
我们把
A[1]
分离出来,可以得到 A [ 1 ] = ( − 1 ) i + 1 ∗ ( A [ i ] − B [ i ] ) A[1] = (-1)^{i+1}* (A[i] - B[i]) A[1]=(−1)i+1∗(A[i]−B[i])因为我们想要的是
A[i] = X[j]
,所以我们对于每个i
,枚举每个X[j]
,计算出要想A[i] = X[j]
时A[1]
的值,我们用map
存一下数量,最后跑一遍map,找到第二键值最大的输出,记得开longlong
#include
using namespace std;
#define endl '\n'
#define inf 0x3f3f3f3f
#define mod7 1000000007
#define mod9 998244353
#define m_p(a,b) make_pair(a, b)
#define mem(a,b) memset((a),(b),sizeof(a))
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
typedef long long ll;
typedef pair <int,int> pii;
#define MAX 300000 + 50
ll n, m, k, x;
ll s[MAX];
ll br[MAX];
void work(){
cin >> n >> m;
for(int i = 1; i < n; ++i){
cin >> s[i];
}
for(int i = 2; i <= n; ++i){
br[i] = s[i - 1] - br[i - 1];
}
map<ll, ll>mp;
for(int j = 1; j <= m; ++j){
cin >> x;
for(int i = 1; i <= n; ++i){
++mp[(x - br[i]) * (i % 2 == 0 ? -1 : 1)];
}
}
ll ans = 0;
for(auto [x, y] : mp)ans = max(ans, y);
cout << ans << endl;
}
int main(){
io;
work();
return 0;
}