[CF549F] Yura and Developers
题外话
怎么没人直接强上笛卡尔树分治。
正文
看到最大值,想一想笛卡尔树分治。
令当前区间为 \(\left [ l, r \right ]\),区间最大值及位置为 \(mx, k\)。
假设 \(\left [ l, k \right ]\) 为短边(另一段为短边时也差不太多)。
满足条件的子段长成 \(sum_i-sum_{j-1}-mx \equiv 0 \left ( \bmod \ k \right )\)。
移一移项,得 \(sum_i \equiv sum_{j-1}+mx \left ( \bmod \ k \right )\)。
开个 map 把右边的 \(sum_i\) 存下来,暴力算左边每个数的贡献就行。
啸细节
存每个长边 \(sum_i\) 的 map 可以直接一层层传下去,不要重新统计。
map 换成 __gnu_pbds::gp_hash_table(详见这里)。
代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#define int long long
using namespace std;
inline int read()
{
int f = 0, ans = 0;
char c = getchar();
while (!isdigit(c))
f |= c == '-', c = getchar();
while (isdigit(c))
ans = (ans << 3) + (ans << 1) + c - 48, c = getchar();
return f ? -ans : ans;
}
void write(int x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
const int N = 3e5 + 5;
int n, _K, a[N];
int ans, s[N];
__gnu_pbds::gp_hash_table<int, int> mp;
template <typename T>
inline T Mod(T &&x) { return x >= _K ? x -= _K : x; }
namespace ST
{
pair<int, int> f[19][N];
inline void init()
{
for (int i = 1; i <= n; ++i)
f[0][i] = {a[i], i};
for (int j = 1; j <= __lg(n); ++j)
for (int i = 1; i + (1 << j) - 1 <= n; ++i)
f[j][i] = max(f[j - 1][i], f[j - 1][i + (1 << j - 1)]);
}
inline pair<int, int> get_max(int l, int r)
{
int lg = __lg(r - l + 1);
return max(f[lg][l], f[lg][r - (1 << lg) + 1]);
}
}
void solve(int l, int r, int d)
{
if (l >= r)
{
ans += l == r;
return;
}
auto [mx, k] = ST::get_max(l, r);
mx %= _K;
if (k - l <= r - k)
{
for (int i = l; i < k; ++i)
--mp[s[i]];
for (int i = l; i <= k; ++i)
ans += mp[Mod(s[i - 1] + mx)];
--mp[s[k]];
solve(k + 1, r, d + 1);
mp.clear();
for (int i = l; i < k; ++i)
++mp[s[i]];
solve(l, k - 1, d + 1);
}
else
{
for (int i = k + 1; i <= r; ++i)
--mp[s[i]];
++mp[s[l - 1]], --mp[s[k]];
for (int i = k; i <= r; ++i)
ans += mp[Mod(s[i] - mx + _K)];
--mp[s[l - 1]];
solve(l, k - 1, d + 1);
mp.clear();
for (int i = k + 1; i <= r; ++i)
++mp[s[i]];
solve(k + 1, r, d + 1);
}
}
signed main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
n = read(), _K = read();
for (int i = 1; i <= n; ++i)
{
Mod(s[i] = s[i - 1] + (a[i] = read()) % _K);
++mp[s[i]];
}
ST::init();
solve(1, n, 0);
write(ans - n);
return 0;
}

浙公网安备 33010602011771号