乱搞 [CodeForces 348C] Subset Sums nsqrtn

来源:互联网 发布:微信宣传模版源码下载 编辑:程序博客网 时间:2024/05/17 05:53

题面去内网找
这道题的思路很神奇,把集合分成了重集合和轻集合。我们把元素个数大于sqrt(n)的集合称为重集合。显然这样的集合超不过sqrt(n)个。
那么就可以分别处理集合了
首先统计出每个集合与每一个重集合交集有多大。维护重集合的sum(总和)和add(这个集合累计加了多少)值。
对于重集合
1.修改:只改一下add就好
2.查询:sum[x]+add所有重集合×与其交集
对于轻集合
1.修改:暴力。
2查询:暴力加+那一堆add
其实这道题的灵感来源于树链剖分的轻重之分

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#define N 100005#define ll long longusing namespace std;struct road{int v,next;}lu[N*4];int n,m,q,h,e,tot,ss[N],adj1[N],adj2[N],vis[N];ll a[N],cnt[N][320],sum[320],add[320];void add1(int u,int v){lu[++e]=(road){v,adj1[u]};adj1[u]=e;}void add2(int u,int v){lu[++e]=(road){v,adj2[u]};adj2[u]=e;}int main(){    //freopen("20.in","r",stdin);    //freopen(".out","w",stdout);    scanf("%d%d%d",&n,&m,&q);ll x,y,z;h=sqrt(n);    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);    for(int i=1;i<=m;i++)    {        scanf("%lld",&y);        if(y>=h)++tot,vis[i]=1,ss[i]=tot;        for(int j=1;j<=y;j++)        {            scanf("%lld",&x),add1(i,x);            if(vis[i]==1)sum[ss[i]]+=a[x],add2(x,ss[i]);        }    }    for(int i=1;i<=m;i++)        for(int k=adj1[i];k;k=lu[k].next)        {            int to=lu[k].v;            for(int j=adj2[to];j;j=lu[j].next)                cnt[i][lu[j].v]++;        }    ll ans=0;    while(q--)    {        scanf("%lld",&z);        if(z==1)        {            scanf("%lld",&x);ans=0;            if(!vis[x])            {                for(int i=adj1[x];i;i=lu[i].next)ans+=a[lu[i].v];                for(int i=1;i<=tot;i++)ans+=add[i]*cnt[x][i];            }            else            {                ans=sum[ss[x]];                for(int i=1;i<=tot;i++)ans+=add[i]*cnt[x][i];            }            printf("%lld\n",ans);        }        else        {            scanf("%lld%lld",&x,&y);            if(!vis[x])            {                for(int i=adj1[x];i;i=lu[i].next)a[lu[i].v]+=y;                for(int i=1;i<=tot;i++)sum[i]+=y*cnt[x][i];            }            else add[ss[x]]+=y;        }    }}