Codeforces348C - Subset Sums

2024-03-19 18:08
文章标签 sums subset codeforces348c

本文主要是介绍Codeforces348C - Subset Sums,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Portal

Description

给出长度为\(n(n\leq10^5)\)的序列\(\{a_n\}\)以及\(m(m\leq10^5)\)个下标集合\(\{S_m\}(\sum|S_i|\leq10^5)\),进行\(q(q\leq10^5)\)次操作:

  • 询问下标属于集合\(S_k\)的所有数之和。
  • 将下标属于集合\(S_k\)的所有数加\(x\)

Solution

\(N_0=\sqrt{\sum|S_i|}\)
我们把集合划分成轻集合与重集合,大小超过\(N_0\)的集合就是重集合。容易知道重集合的个数不超过\(N_0\)。对于每个重集合,记录sum表示该集合的和,add表示该集合总体被加了的值,cnt[i]表示该集合与集合\(i\)的交集大小。
询问时,如果是重集合则输出sum;否则暴力求\(\{a\}\)上的和,再加上每个重集合对该轻集合的贡献add*cnt[k]
修改时,如果是重集合则add+=x;否则暴力修改\(\{a\}\)。然后更新每个重集合的sum,也就是加上x*cnt[k]

时间复杂度\(O(q\sqrt{\sum|S_i|})\)

Code

//Subset Sums
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long lint;
inline int read()
{int x=0,f=1; char ch=getchar();while(ch<'0'||'9'<ch) {if(ch=='-') f=-1; ch=getchar();}while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar();return x*f;
}
int const N=1e5+1e3;
int const N0=400;
int n,m,q,n0; lint a[N];
int ori[N];
struct _set{int siz,id; vector<int> x;} s[N];
bool cmpSiz(_set x,_set y) {return x.siz>y.siz;}
bool tmp[N]; int cnt[N0][N]; lint add[N0],sum[N0];
int main()
{n=read(),m=read(),q=read();for(int i=1;i<=n;i++) a[i]=read();int sumK=0;for(int i=1;i<=m;i++){s[i].siz=read(),s[i].id=i,s[i].x.push_back(0); sumK+=s[i].siz;for(int p=1;p<=s[i].siz;p++) s[i].x.push_back(read());}sort(s+1,s+m+1,cmpSiz);for(int i=1;i<=m;i++) ori[s[i].id]=i;n0=sqrt(sumK); int cnt1=0;for(int i=1;s[i].siz>=n0;i++) cnt1=i;for(int i=1;i<=cnt1;i++){memset(tmp,false,sizeof tmp);for(int p=1;p<=s[i].siz;p++) sum[i]+=a[s[i].x[p]],tmp[s[i].x[p]]=true;for(int j=1;j<=m;j++)for(int p=1;p<=s[j].siz;p++) if(tmp[s[j].x[p]]) cnt[i][j]++;}for(int owo=1;owo<=q;owo++){char opt; scanf("%c",&opt);if(opt=='?'){int k=ori[read()];if(k<=cnt1) printf("%lld\n",sum[k]);else{lint res=0;for(int p=1;p<=s[k].siz;p++) res+=a[s[k].x[p]];for(int i=1;i<=cnt1;i++) res+=add[i]*cnt[i][k];printf("%lld\n",res);}}if(opt=='+'){int k=ori[read()]; lint v=read();if(k<=cnt1) add[k]+=v;else for(int p=1;p<=s[k].siz;p++) a[s[k].x[p]]+=v;for(int i=1;i<=cnt1;i++) sum[i]+=v*cnt[i][k];}}return 0;
}

P.S.

可以用vector<int>存储集合元素,直接开数组内存太大。
要开long long啊啊啊啊啊!

转载于:https://www.cnblogs.com/VisJiao/p/8492216.html

这篇关于Codeforces348C - Subset Sums的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/826837

相关文章

【SPOJ】Triple Sums【FFT】

传送门:【SPOJ】Triple Sums 题目分析: 首先我们不考虑 i<j<k i<j<k这个条件,构造多项式: Y=∑xai \qquad\qquad\qquad Y = \sum x^{a_i} 那么 ai+aj+ak=S ai+aj+ak=S的个数即 xai+aj+ak=S x^{a_i+a_j+a_k=S}的个数,等价于 Y3中xS Y^3中x^S的系数。 然后我们考虑容斥

codeforces 289 C Sums of Digits

贪心,做了两个半小时没做出来!主要在于求有k位且恰比某个数大的最小值,从左到右检查可以加1的位,若后面的位满足条件,再根据solve中的方法满足条件的最小值。 #include<iostream>#include<string>#include<cstring>#include<cstdio>#include<cmath>#include<iomanip>#include<map

UVA11997K Smallest Sums(优先队列+二路归并)

题目:UVA11997K Smallest Sums(优先队列+二路归并) 题目大意:求K个最小和。给出K行,每行有K个数,在每行中取一个元素相加,求这些和中最小的k的值。 解题思路:每一行排列一下,那么对于两张表a1< a2 < a3 < a4... ,可以将a1 + b1(最小的), a1+ b2, a1 + b3...a1 + bk存到优先队列中,然后最小的出队,就尝试将剩余

PyTorch数据子集采样精粹:torch.utils.data.Subset深度解析

标题:PyTorch数据子集采样精粹:torch.utils.data.Subset深度解析 在深度学习项目中,对数据集进行有效的子集采样是常见需求,无论是为了创建训练集和测试集,还是进行K折交叉验证。PyTorch的torch.utils.data.Subset工具为此提供了一个简洁而强大的解决方案。本文将详细探讨Subset的使用方法,并展示如何通过代码实现数据子集的采样,以增强模型的泛化能

【规律题】Backward Digit Sums

【POJ3187】【洛谷1118】Backward Digit Sums Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Problem Description FJ and his cows enjoy playing a mental game. They write do

全子集问题(subset)

全子集问题的三种解法: 1.回溯法 回溯是经典的解法,有固定的模板,用递归实现。 class Solution {public:vector<vector<int>> subsets(vector<int>& nums) {sort(nums.begin(), nums.end());vector<vector<int>> subs;vector<int>

LeetCode刷题 | Day 3 分割等和子集(Partition Equal Subset Sum)

LeetCode刷题 | Day 3 分割等和子集(Partition Equal Subset Sum) 文章目录 LeetCode刷题 | Day 3 分割等和子集(Partition Equal Subset Sum)前言一、题目概述二、解题方法2.1 动态规划思想2.1.1 思路讲解2.1.2 伪代码 + 逐步输出示例2.1.3 Python代码如下2.1.4 C++代码如下

122 Triangular Sums

Triangular Sums 时间限制: 3000 ms  |  内存限制: 65535 KB 难度: 2 描述 The nth Triangular number, T(n) = 1 + … + n, is the sum of the first n integers. It is the number of points in a triangula

uva 11997 - K Smallest Sums(优先队列)

题目链接:uva 11997 - K Smallest Sums 题目大意:有k个整数数组,包含k个元素,在每个数组中取一个元素加起来可以得到k

ICPC 6929 Sums

思路 :如果一个数n是2的阶乘,那么是无解的。 然后,如果N是奇数,那么肯定能由中间的两个数相加得到。如果N是偶数,就要分成两种情况,一种是 取 n-1 n n+1等等,n的左右两边可以取I个值,可以发现n-2和n+2相加和n-1加n+1相加相等。。另一种情况就是中间情况是 n-1 n n+1,n-1和n的值等于n-2和n+1的值。。 贴上JYJJ阿姨的代码