乱搞 [CodeForces 348C] Subset Sums nsqrtn

题面去内网找
这道题的思路很神奇,把集合分成了重集合和轻集合。我们把元素个数大于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 long
using 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
",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;
        }
    }
}
原文地址:https://www.cnblogs.com/QTY2001/p/7674423.html