[Codeforces348C]Subset Sums(乱搞)
来源:互联网 发布:雪白血红 张正隆知乎 编辑:程序博客网 时间:2024/06/05 20:06
=== ===
这里放传送门
=== ===
题解
这玩意儿算啥算法啊。。说它是乱搞吧,它其实也挺机智的;但是好像ATP知道的任何一种除了乱搞以外的算法都不能描述它。。。
这道题的意思是给定一个数列和
这题的难点就在于对一个集合的修改可能会影响到好多别的集合的数字和,关键就是怎么解决这个问题。然而我们可以发现因为题目中告诉我们集合总大小不超过
然后考虑如果只有大小大于
那把这两种情况结合一下就有一种科学的做法了。设大小小于
修改S类集合的时候首先暴力修改原序列以方便S类集合的求和操作,然后要考虑对B类集合造成的影响。这个时候我们预处理一个大小为
对于S类集合的求和操作,先枚举原序列中的元素,这样可以统计S类集合的修改对它造成的影响;因为B类集合的增量没有累加到原序列里,所以枚举所有B类集合,把增量*交集大小累加到答案里。对于B类集合的求和操作,因为S类集合的增量已经累加过来了,所以直接枚举其它的B类集合累加增量就可以了。
可以发现对于S类集合的操作是和它的集合大小成正比的,对于B类集合的操作是和它的集合个数成正比的。总复杂度是
代码
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,q,tot,rec[100010],cnt[100010][360],num[360],Limit,W,tmp[100010];long long delta[360],sum[360],a[100010];struct Set{ int k,l,r;}s[100010];long long AskBig(int now){ int pos=tmp[now]; long long ans=sum[pos]; for (int i=1;i<=W;i++) ans+=(long long)cnt[now][i]*delta[i]; return ans;}long long AskSmall(int now){ long long ans=0; for (int i=s[now].l;i<=s[now].r;i++) ans+=a[rec[i]]; for (int i=1;i<=W;i++) ans+=(long long)cnt[now][i]*delta[i]; return ans;}void ChangeSmall(int now,int v){ for (int i=s[now].l;i<=s[now].r;i++) a[rec[i]]+=v; for (int i=1;i<=W;i++) sum[i]+=(long long)cnt[now][i]*v;}int main(){ scanf("%d%d%d",&n,&m,&q); Limit=ceil(sqrt(n)); for (int i=1;i<=n;i++) scanf("%I64d",&a[i]); for (int i=1;i<=m;i++){ int k;scanf("%d",&k); s[i].k=k;s[i].l=tot+1; for (int j=1;j<=k;j++){ int x;scanf("%d",&x); rec[++tot]=x; }s[i].r=tot; if (k>Limit) num[++W]=i; } for (int i=1;i<=W;i++){ int u=num[i]; for (int j=s[u].l;j<=s[u].r;j++){ ++tmp[rec[j]]; sum[i]+=a[rec[j]]; } for (int j=1;j<=m;j++) for (int k=s[j].l;k<=s[j].r;k++) cnt[j][i]+=tmp[rec[k]]; for (int j=s[u].l;j<=s[u].r;j++) --tmp[rec[j]]; } for (int i=1;i<=W;i++) tmp[num[i]]=i; for (int i=1;i<=q;i++){ char c=getchar(); int x,v; while (c!='?'&&c!='+') c=getchar(); if (c=='?'){ scanf("%d",&x); if (s[x].k>Limit) printf("%I64d\n",AskBig(x)); else printf("%I64d\n",AskSmall(x)); }else{ scanf("%d%d",&x,&v); if (s[x].k>Limit) delta[tmp[x]]+=v; else ChangeSmall(x,v); } } return 0;}
偏偏在最后出现的补充说明
这种按照大数据和小数据分类讨论的思路有时候可以解决一些用普通方法很难解决的问题。考虑的时候要注意对于两种类型的元素的特点设计复杂度合适的算法,每一种类型的元素进行操作的时候都要考虑另外一种元素的影响。
- [Codeforces348C]Subset Sums(乱搞)
- 乱搞 [CodeForces 348C] Subset Sums nsqrtn
- Subset Sums
- Subset Sums
- Subset Sums
- Subset Sums
- 【USACO】Subset Sums(双向搜索 dfs)
- USACO-Section 2.2 Subset Sums (DP)
- USACO - 2.2 Subset Sums(DP)
- CodeForces 348 C.Subset Sums(分块)
- 洛谷P1466 集合 Subset Sums(dp)
- USACO 2.2 Subset Sums (subset)
- USACO2.2.2 Subset Sums (subset)
- USACO2.2.2 Subset Sums (subset)
- Section 2.2 Subset Sums
- USACO 2.2 Subset Sums
- 2.2Subset Sums
- usaco training-Subset Sums
- ASP.NET 学习笔记
- Common Clock Framework系统结构
- AnimationListener--mars第2季第11集
- App中集成友盟sdk实现下载统计
- test
- [Codeforces348C]Subset Sums(乱搞)
- springmvc获取页面的参数
- js 平时积累
- iOS之教训(不是技术文)
- 黄金连分数
- java倒计时
- ubuntu mysql远程连接
- Unity中继承MonoBehavior类的如何实现类似单例
- phpstorm黑色主题