• Wannafly挑战赛21 E 未来城市规划


    Wannafly挑战赛21 E 未来城市规划


    https://www.nowcoder.com/acm/contest/159/E

    数据结构好题orz

    先看看一条边在一个子树里的贡献,就是这条边的权值×一边的点数×另一边的点数

    设子树的树根是(x),这条边连接的深度较大的点是(y)

    那么贡献就是(W(siz_y)(siz_x-siz_y))

    (W(siz_xsiz_y-siz_y^2))

    边权放到点上,对每个点维护(Wsiz)(Wsiz^2)即可。

    注意nowcoder的clang++非常锅锅,尽量开全局变量,不然main里的n可能就随便从5变成67了(调了1h mmp)

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    #define mod 2019
    typedef long long ll;
    il int gi(){
    	int x=0,f=1;
    	char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')f=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    int W[50010];
    int fir[50010],dis[50010],nxt[50010],id;
    il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
    int dfn[50010],redfn[50010],siz[50010],son[50010],dep[50010],fa[50010];
    il vd dfs1(int x){
    	siz[x]=1;
    	for(int i=fir[x];i;i=nxt[i]){
    		dep[dis[i]]=dep[x]+1;
    		dfs1(dis[i]);
    		siz[x]+=siz[dis[i]];
    		if(siz[dis[i]]>siz[son[x]])son[x]=dis[i];
    	}
    }
    int top[50010];
    il vd dfs2(int x,int tp){
    	dfn[x]=++dfn[0];redfn[dfn[0]]=x;
    	top[x]=tp;
    	if(son[x])dfs2(son[x],tp);
    	for(int i=fir[x];i;i=nxt[i])if(dis[i]!=son[x])dfs2(dis[i],dis[i]);
    }
    int s1[200010],s2[200010],S1[200010],S2[200100],lz[200010];
    #define mid ((l+r)>>1)
    il vd Inc(int x,const int&t){
    	S1[x]=(S1[x]+s1[x]*t)%mod;
    	S2[x]=(S2[x]+s2[x]*t%mod)%mod;
    	lz[x]=(lz[x]+t)%mod;
    }
    il vd down(const int&x){if(lz[x])Inc(x<<1,lz[x]),Inc(x<<1|1,lz[x]),lz[x]=0;}
    il vd upd(const int&x){
    	S1[x]=S1[x<<1]+S1[x<<1|1];
    	S2[x]=S2[x<<1]+S2[x<<1|1];
    }
    il vd build(int x,int l,int r){
    	if(l==r){
    		int p=redfn[l];
    		s1[x]=siz[p],s2[x]=siz[p]*siz[p]%mod;
    		S1[x]=s1[x]*W[p]%mod,S2[x]=s2[x]*W[p]%mod;
    		return;
    	}
    	build(x<<1,l,mid),build(x<<1|1,mid+1,r);
    	upd(x);
    	s1[x]=(s1[x<<1]+s1[x<<1|1])%mod;
    	s2[x]=(s2[x<<1]+s2[x<<1|1])%mod;
    }
    il vd update(int x,int l,int r,const int&L,const int&R,const int&d){
    	if(L<=l&&r<=R)return Inc(x,d);
    	down(x);
    	if(L<=mid)update(x<<1,l,mid,L,R,d);
    	if(mid<R)update(x<<1|1,mid+1,r,L,R,d);
    	upd(x);
    }
    il std::pair<int,int> operator +(const std::pair<int,int>&a,const std::pair<int,int>&b){return std::make_pair(a.first+b.first,a.second+b.second);}
    il std::pair<int,int> query(int x,int l,int r,const int&L,const int&R){
    	if(L<=l&&r<=R)return std::make_pair(S1[x],S2[x]);
    	down(x);
    	if(L<=mid)
    		if(mid<R)return query(x<<1,l,mid,L,R)+query(x<<1|1,mid+1,r,L,R);
    		else return query(x<<1,l,mid,L,R);
    	else return query(x<<1|1,mid+1,r,L,R);
    }
    int n,q;
    int main(){
        n=gi(),q=gi();
    	for(int i=2;i<=n;++i)fa[i]=gi(),W[i]=gi(),link(fa[i],i);
    	dfs1(1),dfs2(1,1);
    	build(1,1,n);
    	char opt[2];int u,v,w;
    	while(q--){
    		scanf("%s",opt);
    		if(opt[0]=='I'){
    			u=gi(),v=gi(),w=gi();
    			if(u==v)continue;
    			while(top[u]!=top[v]){
    				if(dep[top[u]]>dep[top[v]])update(1,1,n,dfn[top[u]],dfn[u],w),u=fa[top[u]];
    				else update(1,1,n,dfn[top[v]],dfn[v],w),v=fa[top[v]];
    			}
    			if(dfn[u]>dfn[v])std::swap(u,v);
    			update(1,1,n,dfn[u]+1,dfn[v],w);
    		}else{
    			w=gi();
    			if(siz[w]==1){puts("0");continue;}
    			std::pair<int,int>A=query(1,1,n,dfn[w]+1,dfn[w]+siz[w]-1);
    			A.first%=mod,A.second%=mod;
    			printf("%d
    ",(A.first*siz[w]-A.second+mod)%mod);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    [转]CentOS 修改yum源为国内源
    著名的镜像网站
    [译]LRTHW练习五——更多的变量及输出打印
    CentOS足迹一
    LRTHW笔记二
    线程的创建和运行(未完待续)
    比较当前时间和给定时间大小
    单独管理image
    Java 修改页面排序条件
    Java 如何使用radio button保存值
  • 原文地址:https://www.cnblogs.com/xzz_233/p/9721143.html
Copyright © 2020-2023  润新知