题目链接:HDU4858
【分析】BC round#1里面的,当时没做出来,后来也没补上,最近看到了才补上。是一道分块题,当时好像可以暴力过,杭电编译器升级之后暴力似乎不太可能了(反正我是没暴力过)。
首先可以把每个点按照度数分成两类:重点和轻点,类似分块的块数和每块的大小这样分,定义>=sqrt(n)是重点,否则为轻点,这样重点最多只有sqrt(m)个,因为只有2*m条边。然后轻点可能有很多,所以需要一个sum[i]维护和i相邻的所有轻点权值之和,重点只记录他自己的权值val[i];对于每个查询操作u:把所有相邻的重点权值相加,对于相邻的轻点直接加上sum[u],由于重点最多只有sqrt(m)个,所以复杂度是sqrt(m); 然后对于修改操作u,v:如果u是重点则直接修改自身val[u]即可(因为sum只记录轻点),如果u是轻点,则把u相邻的所有点的sum修改即可,复杂度也是sqrt(m)的,因为轻点的定义就是度小于sqrt(m)呀。这样总的复杂度就是q*sqrt(m)。
【AC CODE】452ms
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
//#include <unordered_set>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 100000+10, MAXM = 100000*2+20, SIZE = 150;
struct G{
int head[MAXN], tol,nxt[MAXM],to[MAXM];
void add_edge(int u, int v)
{
nxt[tol] = head[u], to[tol] = v;
head[u] = tol++;
}
void clear()
{
clc(head,-1);
tol = 0;
}
}z,q;/*轻重点分开存--保证复杂度单次sqrt(n)*/
struct Edge{
int u,v;
}edge[MAXM];
int val[MAXN], du[MAXN], sum[MAXN];//sum[i]与i相邻的所有du<SIZE的权和
int main()
{
#ifdef SHY
freopen("d:\\1.txt", "r", stdin);
#endif
int t;
scanf("%d%*c", &t);
while(t--)
{
int n,m;
scanf("%d %d%*c", &n, &m);
clc(val,0);
clc(du,0);
clc(sum,0);
rep(i,0,m)
{
int u,v;
scanf("%d %d%*c", &u, &v);
edge[i] = {u,v};
du[v]++, du[u]++;
}
z.clear();
q.clear();
rep(i,0,m)
{
int u = edge[i].u,v = edge[i].v;
if(du[v] >= SIZE) z.add_edge(u,v);
else q.add_edge(u,v);
if(du[u] >= SIZE) z.add_edge(v,u);
else q.add_edge(v,u);
}
int cnt;
scanf("%d%*c", &cnt);
while(cnt--)
{
int op;
scanf("%d%*c", &op);
if(op)//查询
{
int u;
scanf("%d%*c", &u);
int ans = sum[u];
for(int i = z.head[u]; ~i; i = z.nxt[i])
ans += val[z.to[i]];
printf("%d\n", ans);
}
else
{
int u,v;
scanf("%d %d%*c", &u, &v);
if(du[u] >= SIZE) val[u] += v;
else
{
//sum[u] += v;
for(int i = q.head[u]; ~i; i = q.nxt[i])
sum[q.to[i]] += v;
for(int i = z.head[u]; ~i; i = z.nxt[i])
sum[z.to[i]] += v;
}
}
}
}
return 0;
}