E−分类讨论−思路:
如果两个人之间差值x为偶数,那么两人达到同一行那一步是由Alice迈出的。
注意到吃掉别人当且仅当你迈出一步,和他到同一行并且把他吃掉。
所以如果差值是偶数,要么Alice赢,要么平局。反之亦然。
算一下两人见面之前的y的范围,判一下进攻方[l1,r1],防守方[l2,r2],
是否满足l1<=l2+1,r1>=r2−1,
如果满足就肯定可以吃掉,否则平局。
然后特判一下两个人永远不会同一行的情况。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <unordered_map>
#include <vector>
#include <queue>
#include <set>
#define IOS cin.tie(nullptr)->ios::sync_with_stdio(false);
#define endl '\n'
#define int long long
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 1000010,MOD = 998244353;
int h,w,xa,xb,ya,yb;
int T;
int ans;
void solve()
{
cin>>h>>w>>xa>>ya>>xb>>yb;
if(xa >= xb)
{
cout<<"Draw"<<endl;
return;
}
int dist = xb - xa;
int la = max(1ll,ya - dist/2), ra = min(w,ya + dist/2);
if(dist & 1)
{
int lb = max(1ll,yb - dist/2), rb = min(w,yb + dist/2);
if(la <= lb + 1 && ra >= rb - 1) cout<<"Alice"<<endl;
else cout<<"Draw"<<endl;
}else
{
int lb = max(1ll,yb - (dist-1)/2), rb = min(w,yb + (dist-1)/2);
if(lb <= la + 1 && rb >= ra - 1) cout<<"Bob"<<endl;
else cout<<"Draw"<<endl;
}
}
signed main(){
IOS
cin>>T;
while(T -- )
{
solve();
}
return 0;
}
F−根号分治+带权前缀和
题目分析:给定n个数,给定q个询问,每组询问包含s(起点),d(步长),k(个数),
求对应序列as+as+d⋅2+⋯+as+d⋅(k−1)⋅k之和,保证最后一项下标一定小于n
对于d=1的情况,所求序列和为连续子数组,可以用带权前缀和O(1)得到
带权子数组和[l,r):sumr−suml−l⋅(al+al+1+···+ar−1)
即为sumr−suml−l⋅(prer−prel)
对于d=2的情况
sum0=0,sum1=0;
sum2=1⋅a0,sum3=1⋅a1;
sum4=1⋅a0+2⋅a2,sum5=1⋅a1+2⋅a3
即sumi+2=sumi+(i/2+1)⋅ai
令prei+2=prei+ai
带权子数组和[l,r+2):即为sumr+2−suml−(l/2)⋅(prer+2−prel)
归纳得:元素和为sumr+d−suml−(l/d)⋅(prer+d−prel)
预处理要同时处理步长和前缀和,但是预处理全部步长会爆空间和时间
因此我们只处理小于√n的步长,这里直接取最大值320,预处理复杂度近似为O(nlogn)
对于步长大于等于√n的情况,直接暴力求,时间复杂度O(√n)
#include <bits/stdc++.h>
using namespace std;
const int MX_N = 100010, B = 320;
int64_t pre[B][MX_N+B], sum[B][MX_N+B];
void solve() {
int n, q;
cin >> n >> q;
vector<int64_t> a(n);
for (auto &v: a) {
cin >> v;
}
for (int d = 1; d < B; d++) {
for (int i = 0; i < n; i++) {
pre[d][i + d] = pre[d][i] + a[i];
sum[d][i + d] = sum[d][i] + a[i] * (i / d + 1);
}
}
while (q--) {
int s, d, k;
cin >> s >> d >> k;
s--;
if (d < B) {
int r = s + d * k;
cout << sum[d][r] - sum[d][s] - (pre[d][r] - pre[d][s]) * (s / d) << " ";
} else {
int64_t res = 0;
for (int i = 0; i < k; i++) {
res += a[s + d * i] * (i + 1);
}
cout << res << " ";
}
}
cout << '\n';
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T;
for (cin >> T; T--;) {
solve();
}
return 0;
}