默认 同阶。
大小 的称为小集合, 的称为大集合,其中大集合的个数不超过 个。
可以提前 地预处理出与其他所有集合之间有多少重复的元素,开个桶就可以。
对于每个大集合,直接记录 为集合内所有数的和,记录一个 代表 操作给这个集合加了多少。
对于大集合的修改: 复杂度内给其他每个大集合记录下产生贡献(通过预处理已经可以 算出 应该增长多少)。
对于小集合的修改:给原数组对应处的位置加上数,然后也是将 个大集合的 加上某个数。
对于大集合的询问:大集合和小集合的修改都已经修改到了 上,所以答案就是对应的 .
对于小集合的询问:首先 遍历原数组对应处位置,能知道小集合的修改对其的贡献;然后遍历 个大集合,根据预处理和 的记录能够 算出大集合的修改对其的贡献。
综上所述,复杂度为 .
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<unordered_map>
#define pb emplace_back
#define mp std::make_pair
#define fi first
#define se second
typedef long long ll;
typedef std::pair<int, int> pii;
typedef std::pair<ll, int> pli;
typedef std::pair<ll, ll> pll;
typedef std::vector<int> vi;
typedef std::vector<ll> vll;
const ll mod = 998244353;
ll Add(ll x, ll y) { return (x+y>=mod) ? (x+y-mod) : (x+y); }
ll Mul(ll x, ll y) { return x * y % mod; }
ll Mod(ll x) { return x < 0 ? (x + mod) : (x >= mod ? (x-mod) : x); }
ll cadd(ll &x, ll y) { return x = (x+y>=mod) ? (x+y-mod) : (x+y); }
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T &read(T &r) {
r = 0; bool w = 0; char ch = getchar();
while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
return r = w ? -r : r;
}
const int N = 100010;
const int B = 316;
int n, m, q;
int siz[N];
vi s[N];
ll w[N], v[N], a[N];
int vis[N], cnt[B+10][N], pos[N], rk[N], pct;
void calc(int p) {
for(auto x : s[p]) vis[x] = 1, w[p] += a[x];
for(int i = 1; i <= m; ++i)
for(auto x : s[i])
if(vis[x])
++cnt[pos[p]][i];
for(auto x : s[p]) vis[x] = 0;
}
signed main() {
read(n); read(m); read(q);
for(int i = 1; i <= n; ++i) read(a[i]);
for(int i = 1; i <= m; ++i) {
read(siz[i]);
for(int j = 1, x; j <= siz[i]; ++j) read(x), s[i].pb(x);
}
for(int i = 1; i <= m; ++i)
if(siz[i] > B)
pos[i] = ++pct, rk[pct] = i, calc(i);
for(int o = 1; o <= q; ++o) {
char ch = getchar(); int k, x;
while(ch != '?' && ch != '+') ch = getchar();
if(ch == '+') {
read(k); read(x);
if(siz[k] > B) {
v[k] += x;
for(int i = 1; i <= pct; ++i)
w[rk[i]] += 1ll * cnt[i][k] * x;
}
else {
for(auto i : s[k]) a[i] += x;
for(int i = 1; i <= pct; ++i)
w[rk[i]] += 1ll * cnt[i][k] * x;
}
}
else {
read(k);
if(siz[k] > B) printf("%lld\n", w[k]);
else {
ll ans = 0;
for(auto i : s[k]) ans += a[i];
for(int i = 1; i <= pct; ++i)
ans += v[rk[i]] * cnt[i][k];
printf("%lld\n", ans);
}
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?