HDU 4858 项目管理(点分块)

题意:给出一张图,两种操作
1.将点x加上权值y
2.询问与点x相邻点的权值和

分析:将点分为重点和轻点,度数大于等于 sqrtm 为重点,小于的为轻点,将重点和相邻重点连边,轻边和相邻所有边连边,得到规律,重点的答案是由周围重点和轻点对它的加成组成,而轻点答案直接由相邻点组成,复杂度 Oqsqrtm

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 200004

int n,m;
int x[maxn],y[maxn];
int fir[maxn],nex[maxn],v[maxn],e_max;
int in[maxn];
int sum[maxn],val[maxn];
bool heavy[maxn];

void init()
{
    memset(sum,0,sizeof sum);
    memset(val,0,sizeof val);
    memset(heavy,false,sizeof heavy);
    memset(in,0,sizeof in);
    memset(fir,-1,sizeof fir);
    e_max=0;
}

void add_edge(int s,int t)
{
    int e=e_max++;
    v[e]=t;
    nex[e]=fir[s];
    fir[s]=e;
}

void build()
{
    int block=sqrt(m);
    for(int i=1; i<=n; i++)
    {
        if(in[i]>=block) heavy[i]=true;
    }
    for(int i=0; iint u=x[i],v=y[i];
        if(heavy[u]&&heavy[v])
        {
            add_edge(u,v);
            add_edge(v,u);
        }
        if(!heavy[u]) add_edge(u,v);
        if(!heavy[v]) add_edge(v,u);
    }
}

void update(int x,int y)
{
    val[x]+=y;
    if(!heavy[x])
    {
        for(int i=fir[x]; ~i; i=nex[i])
        {
            int e=v[i];
            sum[e]+=y;
        }
    }
}

int query(int x)
{
    int ans=0;
    if(heavy[x]) ans+=sum[x];
    for(int i=fir[x]; ~i; i=nex[i])
    {
        int e=v[i];
        ans+=val[e];
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=0; iscanf("%d%d",&x[i],&y[i]);
            in[x[i]]++;
            in[y[i]]++;
        }
        build();
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int op;
            scanf("%d",&op);
            if(!op)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                update(x,y);
            }
            else
            {
                int x;
                scanf("%d",&x);
                printf("%d\n",query(x));
            }
        }
    }
    return 0;
}

你可能感兴趣的:(===数据结构===,分块)