Codeforces 348C - Subset Sums(根号分治)
对于这类不好直接维护的数据结构,第一眼应该想到……
根号分治!
我们考虑记【大集合】为大小 \(\geq\sqrt{n}\) 的集合,【小集合】为大小 \(<\sqrt{n}\) 的集合。
显然,查询/修改小集合的时候,直接暴力跑一遍不会出问题,时间复杂度 \(\mathcal O(n\sqrt{n})\)。
关键在于怎样处理【大集合】:
- 修改大集合的时候,暴力一个一个元素修改显然不行,于是考虑整体打一个 \(+v\) 的标记 \(tag_x\)
- 查询大集合的时候我们也不能遍历一遍集合求和,于是可以维护一个数组 \(ans_x\) 表示大集合 \(x\) 的答案,查询的时候直接输出 \(ans_x\)。
这样又有一个问题了,怎样将大集合的贡献累加入答案中。
注意到大集合有一个性质,那就是大集合的个数不会超过 \(\sqrt{n}\)。
故每一次集合整体加值的时候,暴力修改每个大集合的 \(ans_x\);询问小集合的时候,将每个大集合的 \(tag_x\) 累加进答案中。
至于怎样计算大集合的贡献,可以维护一个 \(same_{i,j}\) 表示第 \(i\) 个大集合与第 \(j\) 个集合有多少个公共的元素。那么你对某个大集合 \(x\) 做一次 \(+v\) 的操作,它对另一个集合 \(y\) 的贡献应为 \(same_{x,y}\times v\)。
总结下来,就是:
- 修改小集合 \(x\),暴力修改 \(a_i\),并且对于所有大集合 \(y\),令 \(ans_y\) 假设 \(same_{y,x}\times v\)。
- 修改大集合 \(x\),令 \(tag_x\) 加上 \(v\),并且对于所有大集合 \(y\),令 \(ans_y\) 假设 \(same_{y,x}\times v\)。
- 查询小集合 \(x\),暴力遍历一遍集合求出 \(a_i\) 的和,并枚举所有大集合 \(y\),令答案加上 \(same_{y,x}\times tag_y\)。
- 查询大集合 \(x\),直接输出 \(ans_x\) 就行了。
时空复杂度均为 \(n\sqrt{n}\)
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=1;
while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=neg;
}
const int MAXN=1e5;
const int SQRT=316;
int n,m,qu;ll a[MAXN+5];
vector<int> s[MAXN+5];
int bg[SQRT+5],bgnum=0,same[MAXN+5][SQRT+5];
bitset<MAXN+5> vis[SQRT+5];
ll anss[MAXN+5],add[MAXN+5];
int main(){
scanf("%d%d%d",&n,&m,&qu);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=m;i++){
int len;scanf("%d",&len);
for(int j=1;j<=len;j++){
int x;scanf("%d",&x);s[i].pb(x);
anss[i]+=a[x];
}
if(len>=SQRT){
bg[++bgnum]=i;
for(int j=0;j<s[i].size();j++){
vis[bgnum][s[i][j]]=1;
}
}
}
for(int i=1;i<=m;i++)
for(int j=0;j<s[i].size();j++)
for(int k=1;k<=bgnum;k++)
if(vis[k][s[i][j]]) same[i][k]++;
while(qu--){
static char opt[3];scanf("%s",opt+1);
if(opt[1]=='?'){
int x;scanf("%d",&x);
ll ans=0;
if(s[x].size()<SQRT){
for(int j=0;j<s[x].size();j++) ans+=a[s[x][j]];
for(int j=1;j<=bgnum;j++) ans+=1ll*add[bg[j]]*same[x][j];
printf("%lld\n",ans);
} else printf("%lld\n",anss[x]);
} else {
int x,y;scanf("%d%d",&x,&y);
if(s[x].size()<SQRT){
for(int j=0;j<s[x].size();j++) a[s[x][j]]+=y;
for(int j=1;j<=bgnum;j++) anss[bg[j]]+=1ll*y*same[x][j];
} else {
for(int j=1;j<=bgnum;j++) anss[bg[j]]+=1ll*y*same[x][j];
add[x]+=y;
}
}
}
return 0;
}
Codeforces 348C - Subset Sums(根号分治)的更多相关文章
- CodeForces 348C Subset Sums(分块)(nsqrtn)
C. Subset Sums time limit per test 3 seconds memory limit per test 256 megabytes input standard inpu ...
- Codeforces 348C Subset Sums 分块思想
题意思路:https://www.cnblogs.com/jianrenfang/p/6502858.html 第一次见这种思路,对于集合大小分为两种类型,一种是重集合,一种是轻集合,对于重集合,我们 ...
- Codeforces 1039D You Are Given a Tree [根号分治,整体二分,贪心]
洛谷 Codeforces 根号分治真是妙啊. 思路 考虑对于单独的一个\(k\)如何计算答案. 与"赛道修建"非常相似,但那题要求边,这题要求点,所以更加简单. 在每一个点贪心地 ...
- [codeforces 509]C. Sums of Digits
[codeforces 509]C. Sums of Digits 试题描述 Vasya had a strictly increasing sequence of positive integers ...
- 洛谷P1466 集合 Subset Sums
P1466 集合 Subset Sums 162通过 308提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交 讨论 题解 最新讨论 暂时没有讨论 题目描述 对于从1到N (1 ...
- Project Euler 106:Special subset sums: meta-testing 特殊的子集和:元检验
Special subset sums: meta-testing Let S(A) represent the sum of elements in set A of size n. We shal ...
- Project Euler P105:Special subset sums: testing 特殊的子集和 检验
Special subset sums: testing Let S(A) represent the sum of elements in set A of size n. We shall cal ...
- Project Euler 103:Special subset sums: optimum 特殊的子集和:最优解
Special subset sums: optimum Let S(A) represent the sum of elements in set A of size n. We shall cal ...
- Codeforces348C - Subset Sums
Portal Description 给出长度为\(n(n\leq10^5)\)的序列\(\{a_n\}\)以及\(m(m\leq10^5)\)个下标集合\(\{S_m\}(\sum|S_i|\leq ...
随机推荐
- 【MySQL】MySQL(四)存储引擎、索引、锁、集群
MySQL存储引擎 MySQL体系结构 体系结构的概念 任何一套系统当中,每个部件都能起到一定的作用! MySQL的体系结构 体系结构详解 客户端连接 支持接口:支持的客户端连接,例如C.Java.P ...
- Less-25 preg_replace2
Less-25: 核心语句: 各种回显也均有. 通过blacklist,我们可以发现,本题屏蔽了and和or. preg_replace函数中正则表达式后面的i是一个修饰符,代表正则匹配时不区分大小写 ...
- 第四代富士X100F操作学习
前言 本文为自己通过B站的UP主[阿布垃机手册]整理.原视频地址:[阿布垃机手册][布瞎BB]富士 X100F 相机外部按键 拍人像自己的设置 [X100F相机光圈大小支持F2到F16+Auto]光圈 ...
- Vue2源码解读 - 响应式原理及简单实现
直接进入主题了,想必大家都知道实现vue响应式核心方法就是 Object.defineProperty,那就从它开始说 Object.defineProperty 缺点: 深度监听,需要递归到底,一次 ...
- 这样调优之后,单机也能扛下100W连接
1 模拟单机连接瓶颈 我们知道,通常启动一个服务端会绑定一个端口,例如8000端口,当然客户端连接端口是有限制的,除去最大端口65535和默认的1024端口及以下的端口,就只剩下1 024~65 53 ...
- LiveVideoStackCon2021 北京站专访:从上云到创新,视频云的新技术、新场景
伴随着视频技术的进步和标准的迭代,视频产业从模拟进入到数字时代,完成了从电影电视到互联网的媒介转换,并且衍生出了超高清.3D.AR/VR 等多种创新形态.特别是在后疫情的当下,我们可以看到音视频技术领 ...
- 注解,@Qualifier+@Autowired 和 @Resource
摘要: 项目中,对于AOP的使用,就是通过用注解来注入的. 更改之前的注解,是使用:@Qualifier+@Autowired 但是,通过这样注解,在项目启动阶段,需要自动扫描的过程是非常缓慢的, ...
- 升级MySQL8.0的历险记
最近忙于Fighting的项目,所以笔耕有些松懈,实为不该. 刚好遇到需要从MySQL5.7.33升级到MySQL8.0.x的需求,于是记录一下整个升级过程,踩坑而过. 背景梗概:本地docker容器 ...
- Verilog设计技巧实例及实现
Verilog设计技巧实例及实现 1 引言 最近在刷HDLBits的过程中学习了一些Verilog的设计技巧,在这里予以整理.部分操作可能降低代码的可读性和Debug的难度,请大家根据实际情况进行使用 ...
- MySql数据库索引-聚集索引和辅助索引
InnoDB存储引擎索引: B+树索引:不能找到一个给定键值的具体行,能找到的只是被查找数据行所在的页.然后把页加载到内存,在查询所要的数据. 全文索引: 哈希索引:InnoDB会根据表的使用情况自动 ...