hdu4858(分摊复杂度)

版权声明:本人蒟蒻,如有大佬转发,感激不尽,带上我的博客链接即可。 https://blog.csdn.net/qq_36300700/article/details/81558537

借鉴了一位的大佬的思路:https://www.cnblogs.com/HDUjackyan/p/8996172.html

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4858

思路:图的分块。设点i的点权为val[i],与点i相邻的项目的能量值之和为sum[i]。将图中的点分为重点和轻点,重点是那些边的度数超过sqrt(m)(该值可以自己规定)的点,除了重点剩下的点都是轻点。对于构图,重点只和重点建边,轻点可以和所有点建边。每次更新,对于重点i和轻点来说来说都是更新自己的val[i]和相邻点的sum[i]。而对于查询操作来说,重点直接输出sum[i],而轻点则采用暴力做法:遍历其每一个相邻点,答案累加上相邻的val[i]。采用的思想是分摊复杂度的思想

ac代码:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

const int maxn =100000+50;
#define ll long long
vector<int>mp[maxn],G[maxn];
ll val[maxn],sum[maxn],deg[maxn],vis[maxn];

ll T,n,m,Q,cmd,block;

void init()
{
    for(int i=0; i<=n; i++)
    {
        G[i].clear();
        mp[i].clear();
    }
    memset(sum,0,sizeof(sum));
    memset(deg,0,sizeof(deg));
    memset(val,0,sizeof(val));
    memset(vis,0,sizeof(vis));
}

int main()
{

    scanf("%lld",&T) ;
    while(T--)
    {
        init();
        scanf("%lld %lld",&n,&m);
        block=sqrt(m);

        ll a,b;
        for(int i=0; i<m; i++)
        {
            scanf("%lld %lld",&a,&b);
            deg[a]++;
            deg[b]++;
            mp[a].push_back(b);

        }

        for(int i=1; i<=n ;i++)
        {
            if(deg[i]>block)
                vis[i]=1;
        }

        for(int u=1; u<=n; u++)
        {
            for(int j=0; j<mp[u].size(); j++)
            {
                int v=mp[u][j];
                if(vis[u])
                {
                    if(vis[v])
                    {
                     G[u].push_back(v);
                     G[v].push_back(u);
                    }
                    else
                    {
                        G[v].push_back(u);
                    }
                }
                else
                {
                    if(vis[v])
                    {
                        G[u].push_back(v);
                    }
                    else
                    {
                        G[u].push_back(v);
                        G[v].push_back(u);
                    }
                }

            }
        }
        scanf("%lld",&Q);
      ll u,v;
        ll cnt;
         while(Q--)
         {
             scanf("%lld",&cmd);
             if(!cmd)
             {
                 scanf("%lld %lld",&u,&cnt);
                 val[u]+=cnt;
                 for(int i=0; i<G[u].size(); i++)
                 {
                     v=G[u][i];
                     sum[v]+=cnt;
                 }
             }
             else
             {
                 scanf("%lld",&u);
                 if(vis[u])
                    printf("%lld\n",sum[u]);
                 else
                 {
                     sum[u]=0;
                     for(int i=0; i<G[u].size(); i++)
                     {
                         v=G[u][i];
                         sum[u]+=val[v];
                     }
                     printf("%lld\n",sum[u]);
                 }
             }
         }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36300700/article/details/81558537