Ideas and good questions
First, a collection with a collection size greater than or equal to sqrt (n) is called a re-collection, and the remainder is called a light collection, then the number of re-collections is less than or equal to sqrt (n)
F[I][J] Represents the number of identical elements in the first and second sets, which can be preprocessed within O (n*sqrt (n)).
Re-sum[i] represents the element of the I-re-set and, Add[i] represents the increment tag of all elements of the first I-re-collection.
Modify the operation, re-set directly modify Sum[i] and Add[i], light collection of violent changes, while using F[I][J] to modify the re-collection. Ask the operation, re-set the direct output SUM[I], light collection of violence calculation.
Total Complexity O (n*sqrt (n)).
Notice how the collection is stored, and the adjacency matrix is hyper-memory.
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib > #include <algorithm> #define F (I,j,n) for (int. i=j;i<=n;i++) #define D (i,j,n) for (int i=j;i>=n;i--) # Define ll long Long#define maxn 100005using namespace Std;int n,m,q,cnt,tot,block,head[maxn],id[maxn],f[maxn][400];ll A [Maxn],sum[400],add[400];bool g[400][maxn];struct edge_type{int next,to;} E[maxn];inline int read () {int X=0,f=1;char ch=getchar (); while (ch< ' 0 ' | | Ch> ' 9 ') {if (ch== '-') F=-1;ch=getchar ();} while (ch>= ' 0 ' &&ch<= ' 9 ') {x=x*10+ch-' 0 '; Ch=getchar ();} return x*f;} inline void Add_edge (int x,int y) {e[++cnt]= (edge_type) {head[x],y};head[x]=cnt;} int main () {n=read (); M=read (); Q=read (); Block=ceil (sqrt (100000)); F (I,1,n) a[i]=read (); F (i,1,m) {int sz=read (); if (Sz>=block) id[i]=++tot;while (sz--) {int x=read (); if (Id[i]) G[tot][x]=true;add_edge (i,x );}} F (i,1,m) f (j,1,tot) for (int k=head[i];k;k=e[k].next) if (g[j][e[k].to]) f[i][j]++; F (i,1,m) if (Id[i]) for (iNT J=head[i];j;j=e[j].next) Sum[id[i]]+=a[e[j].to];while (q--) {char ch=getchar (); while (ch!= '? ') &&ch!= ' + ') Ch=getchar (); if (ch== '? ') {int X=read (), if (Id[x]) printf ("%i64d\n", Sum[id[x]]); else{ll ans=0;for (int i=head[x];i;i=e[i].next) ans+=a[e[i].to] ; F (I,1,tot) ans+=add[i]*f[x][i];p rintf ("%i64d\n", ans);}} Else{int X=read (), Y=read (); F (I,1,tot) sum[i]+= (LL) y*f[x][i];if (Id[x]) add[id[x]]+=y;else for (int i=head[x];i;i=e[i].next) a[e[i].to]+=y;}}
cf348c subset Sums