P6604 [HNOI2016] 序列 加强版 题解
与最小值相关,考虑求出每个点左右两边第一个小于这个数的点。可以用笛卡尔树或者单调栈维护。
设
设
同理设
考虑求答案时,求出区间最小值位置
考虑求
同理,
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
using namespace std;
const int N = 1e5 + 5;
int n, q, type;
long long a[N];
namespace gen
{
typedef unsigned long long ull;
ull s, a, b, c, lastans = 0;
ull rand()
{
return s ^= (a + b * lastans) % c;
}
};
int pre[N], suf[N];
long long f[N], revf[N];
long long s_f[N], s_revf[N];
int lson[N], rson[N];
int LG2[N];
int ff[N][21], p[N][21];
void Init()
{
memset(ff, 0x7f, sizeof ff);
for (int i = 2; i < N; i++) LG2[i] = LG2[i >> 1] + 1;
for (int i = 1; i <= n; i++) ff[i][0] = a[i], p[i][0] = i;
for (int j = 1; j <= LG2[n]; j++)
{
for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
if (ff[i][j - 1] < ff[i + (1 << (j - 1))][j - 1])
{
ff[i][j] = ff[i][j - 1];
p[i][j] = p[i][j - 1];
}
else
{
ff[i][j] = ff[i + (1 << (j - 1))][j - 1];
p[i][j] = p[i + (1 << (j - 1))][j - 1];
}
}
}
}
int query(int l, int r)
{
int x = LG2[r - l + 1];
return (ff[l][x] < ff[r - (1 << x) + 1][x] ? p[l][x] : p[r - (1 << x) + 1][x]);
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> q >> type;
for (int i = 1; i <= n; i++) cin >> a[i], pre[i] = 0, suf[i] = n + 1;
if (type == 1) cin >> gen::s >> gen::a >> gen::b >> gen::c;
stack<int> st;
for (int i = 1; i <= n; i++)
{
while (st.size() && a[st.top()] > a[i])
{
lson[i] = st.top();
suf[st.top()] = i;
st.pop();
}
int p = (st.size() ? st.top() : 0);
pre[i] = p;
rson[p] = i;
st.push(i);
}
for (int i = 1; i <= n; i++)
{
f[i] = f[pre[i]] + (1LL * i - pre[i]) * a[i];
s_f[i] = s_f[i - 1] + f[i];
}
for (int i = n; i >= 1; i--)
{
revf[i] = revf[suf[i]] + (1LL * suf[i] - i) * a[i];
s_revf[i] = s_revf[i + 1] + revf[i];
}
Init();
unsigned long long res = 0;
while (q--)
{
int l, r;
if (type == 0) cin >> l >> r;
else
{
l = gen::rand() % n + 1, r = gen::rand() % n + 1;
}
if (l > r) swap(l, r);
int place = query(l, r);
long long ans = 0;
ans += 1ll * a[place] * (1ll * r - place + 1) * (1ll * place - l + 1);
ans += 1ll * (1ll * s_f[r] - s_f[place] - f[place] * 1ll * (1ll * r - place));
ans += 1ll * (1ll * s_revf[l] - s_revf[place] - revf[place] * (1ll * place - l));
gen::lastans = (unsigned long long)ans;
res ^= (unsigned long long)ans;
}
cout << res << "\n";
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现