CF1316F Battalion Strength 题解
sto SoyTony orz
这题动态 DP 真能过(
排序后序列的子序列唯一对应原序列的子序列排序后的结果,所以先排序。
设
考虑动态 DP,则有:
每次单点修改相当于排序后序列上单点删除,单点插入,权值线段树维护之。
注意单点删除时矩阵不一定有逆,所以对每个值
修改某值的出现次数时直接查表即可。
常数优化:注意到矩阵是下三角矩阵,所以矩阵乘法可以优化成
复杂度
#include <cstdio>
#include <vector>
#include <algorithm>
#define M 1000000007
#define H(x) lower_bound(b, b + p, x) - b + 1
using namespace std;
int P(long long x, int y)
{
long long q = 1;
for (; y; y >>= 1, x = x * x % M)
if (y & 1)
q = q * x % M;
return q;
}
int n, m, p, a[600050], c[600050], b[600050], w[300050];
long long o;
struct Q
{
int x, y;
} q[300050];
struct S
{
int a[3][3];
S()
{
for (int i = 0; i < 3; ++i)
for (int j = 0; j <= i; ++j)
a[i][j] = 0;
}
S operator*(S b)
{
S c;
for (int i = 0; i < 3; ++i)
for (int j = 0; j <= i; ++j)
{
long long q = 0;
for (int k = j; k <= i; ++k)
q += 1ll * a[i][k] * b.a[k][j];
c.a[i][j] = q % M;
}
return c;
}
} R[600050 << 2];
vector<S> v[600050];
void B(int s, int t, int p)
{
if (s == t)
return void(R[p] = v[s][a[s]]);
int m = s + t >> 1;
B(s, m, p << 1);
B(m + 1, t, p << 1 | 1);
R[p] = R[p << 1] * R[p << 1 | 1];
}
void C(int l, int x, int s, int t, int p)
{
if (s == t)
return void(R[p] = v[s][x]);
int m = s + t >> 1;
if (l <= m)
C(l, x, s, m, p << 1);
else
C(l, x, m + 1, t, p << 1 | 1);
R[p] = R[p << 1] * R[p << 1 | 1];
}
int main()
{
srand(388651);
scanf("%d", &n);
for (int i = o = 1; i <= n; ++i)
scanf("%d", w + i), b[p++] = w[i], o = (o << 1) % M;
scanf("%d", &m);
for (int i = 0; i < m; ++i)
scanf("%d%d", &q[i].x, &q[i].y), b[p++] = q[i].y;
sort(b, b + p);
p = unique(b, b + p) - b;
for (int i = 1; i <= n; ++i)
++a[w[i] = H(w[i])], ++c[w[i]];
for (int i = 0; i < m; ++i)
++c[q[i].y = H(q[i].y)];
for (int i = 1; i <= p; ++i)
{
S z, q;
for (int j = 0; j < 3; ++j)
z.a[j][j] = 1;
v[i].push_back(z);
q.a[1][1] = 1;
q.a[0][0] = q.a[2][2] = 2;
q.a[1][0] = q.a[2][1] = b[i - 1];
q.a[0][1] = q.a[0][2] = q.a[1][2] = q.a[2][0] = 0;
for (int j = 1; j <= c[i]; ++j)
v[i].push_back(v[i].back() * q);
}
B(1, p, 1);
o = P(o, M - 2);
printf("%d\n", R[1].a[2][0] * o % M);
for (int i = 0; i < m; ++i)
{
C(w[q[i].x], --a[w[q[i].x]], 1, p, 1);
C(w[q[i].x] = q[i].y, ++a[q[i].y], 1, p, 1);
printf("%d\n", R[1].a[2][0] * o % M);
}
return 0;
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具