thumbnail
Ynoi Easy Round 2018 星野爱

太菜了,咕一会儿。

星野爱给了你一张无向图 $G$,设 $R(i)$ 为所有与 $i$ 相连的边的另一个端点构成的可重集合,可能有重边,没有自环。

每个节点有权值 $w_i$,初始时都为 $0$,需要维护两种操作。

  • 1,l,r,v,对于 $i\in [l,r]$,$j\in R(i)$,令 $w_j=w_j+v$
  • 2,l,r,计算 $\sum_{i\in[l,r]}\sum_{j\in R(i)}w_j$。

输出的值请对 $2^{64}$ 取模。


能想到把这张图片放到这道题的背景和写出这道题的人都是神人了。1


带权分块。

更具体地,给出一个动态数组 $B_k$ 表示每一个块维护的权值和。我们这样将图加入到数组中:

  1. 初始,$\text{index}=1$,枚举点 $i$。
  2. 若 $size(B_{\text{index}})+size(R_i)>\sqrt{n}$ 则 $\text{index} \longleftarrow \text{index}+1$。
  3. 将 $R_i$ 加入到 $B_{\text{index}}$ 末尾。

很厉害。

因为有 $\sum 点的度数 = 2m$。所以可以看成 $O(n)$。

#define rg for(reg int e=head[u],v=nxt[e];e<head[u]+deg[u];++e,v=nxt[e])
#define N (200010)
#define B 1500
struct OP{int op,l,r;ull val,ans;}r[N];
int n,m,q,rx[N],ry[N],rk[N],in[N],tot,deg[N],head[N],nxt[N<<1],L[N],R[N],k,rev[N];
ull ad[N],sum[N],num[N];
vector<int>e[N];
signed main(){
	io.read(n);io.read(m);io.read(q);
	// Input graph
	rep(i,1,m)io.read(rx[i]),io.read(ry[i]),in[rx[i]]++,in[ry[i]]++;
	// Del useless node
	rep(i,1,n)if(!in[i])rk[i]=rk[i-1];else rk[i]=++tot;
	
	// Dev graph
	rep(i,1,m)e[rk[rx[i]]].pb(rk[ry[i]]),e[rk[ry[i]]].pb(rk[rx[i]]);
	// Add all into a line
	reg int TMPcnt=0;
	rep(i,1,n){
		head[i]=TMPcnt+1;
		for(auto to:e[i])deg[i]++,nxt[++TMPcnt]=to;
	}
	// operator
	rep(i,1,q){
		io.read(r[i].op),io.read(r[i].l),io.read(r[i].r);
		if(r[i].op==1)io.read(r[i].val);
		r[i].l=rk[r[i].l-1]+1;
		r[i].r=rk[r[i].r];
	}
	// sqrt
	n=tot;
	reg int last=1,tmp=0;
	rep(i,1,n+1)if((tmp+=deg[i])>=B||i>n)++k,L[k]=last,R[k]=i-1,last=i,tmp=deg[i];
	rep(id,1,k)rep(i,L[id],R[id])rev[i]=id;
	// solve
	// --single one--
	rep(i,1,q)if(r[i].l<=r[i].r){
		if(r[i].op==1){ //change
			if(rev[r[i].l]==rev[r[i].r]&&(r[i].l!=L[rev[r[i].l]]||r[i].r!=R[rev[r[i].r]])){
				rep(u,r[i].l,r[i].r)rg ad[v]+=r[i].val;
			}else{
				if(r[i].l!=L[rev[r[i].l]])rep(u,r[i].l,R[rev[r[i].l]])rg ad[v]+=r[i].val;
				if(r[i].r!=R[rev[r[i].r]])rep(u,L[rev[r[i].r]],r[i].r)rg ad[v]+=r[i].val;
			}
		}else{ //query
			if(rev[r[i].l]==rev[r[i].r]&&(r[i].l!=L[rev[r[i].l]]||r[i].r!=R[rev[r[i].r]])){
				rep(u,r[i].l,r[i].r)rg r[i].ans+=ad[v];
			}
			if(rev[r[i].l]!=rev[r[i].r]){
				if(r[i].l!=L[rev[r[i].l]])rep(u,r[i].l,R[rev[r[i].l]])rg r[i].ans+=ad[v];
				if(r[i].r!=R[rev[r[i].r]])rep(u,L[rev[r[i].r]],r[i].r)rg r[i].ans+=ad[v];
			}
		}
	}
	// ---full one---
	rep(id,1,k){
		memset(sum,0,sizeof sum);memset(num,0,sizeof num);
		rep(u,L[id],R[id])rg num[v]++;
		rep(u,1,n){rg sum[u]+=num[v];sum[u]+=sum[u-1];};
		ull sgl=0,ful=0;
		rep(i,1,q)if(r[i].l<=r[i].r){
			if(r[i].op==1){
				ful+=r[i].val*(sum[r[i].r]-sum[r[i].l-1]);
				if(r[i].l<=L[id]&&R[id]<=r[i].r)sgl+=r[i].val;
			}else{
				if(r[i].l<=L[id]&&R[id]<=r[i].r)r[i].ans+=ful; //贡献给整块查询
				if(rev[r[i].l]==rev[r[i].r]&&(r[i].l!=L[rev[r[i].l]]||r[i].r!=R[rev[r[i].r]]))
					r[i].ans+=sgl*(sum[r[i].r]-sum[r[i].l-1]);
				if(rev[r[i].l]!=rev[r[i].r]){
					if(r[i].l!=L[rev[r[i].l]])r[i].ans+=sgl*(sum[R[rev[r[i].l]]]-sum[r[i].l-1]);
					if(r[i].r!=R[rev[r[i].r]])r[i].ans+=sgl*(sum[r[i].r]-sum[L[rev[r[i].r]]-1]);
				}
			}
		}
	}
	rep(i,1,q)if(r[i].op==2)io.write(r[i].ans,'\n');
	return 0;
}
下一篇