zoukankan      html  css  js  c++  java
  • c2020HXW,天下我有的 CSP 考前练习赛

    树上的数

    树上统计类的题目可以尝试往 (dsu) (on) (tree) 方向想。

    #include<bits/stdc++.h>
    #define IL inline
    #define LL long long
    #define pb push_back
    using namespace std;
    const int N=3e5+3;
    struct hh{
    	int to,nxt;
    }e[N<<1];
    int n,num,fir[N],a[N],vis[N],pri[N],vv[N],b1[N],b2[N],cc[N],c[N];
    int dep[N],siz[N],son[N];
    LL sum[N],ans;
    vector<int>v[N];
    IL int in(){
    	char c;int f=1;
    	while((c=getchar())<'0'||c>'9')
    	  if(c=='-') f=-1;
    	int x=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    	  x=x*10+c-'0';
    	return x*f;
    }
    IL void ini(int x,int y){e[++num]=(hh){y,fir[x]},fir[x]=num;}
    void init(){
    	for(int i=1;i<N;++i) vv[i]=1,v[i].pb(1);
    	for(int i=2;i<N;++i)
    	  if(!b1[i]){
    	  	v[i].pb(i);
    	  	if(!b2[i]) vv[i]=i,cc[i]=1;
    			for(int j=i+i;j<N;j+=i){
    				if(!b2[i]) vv[j]*=i;
    				cc[j]+=!b2[i],v[j].pb(i),b2[j]=1;
    			}
    			if(!b2[i]&&i<=2000) for(int j=i*i;j<N;j+=i*i) b1[j]=1;
    		}
    }
    void dfs1(int u,int fa){
    	siz[u]=1,dep[u]=dep[fa]+1;
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^fa){
    	  	dfs1(v,u),siz[u]+=siz[v];
    	  	if(siz[son[u]]<siz[v]) son[u]=v;
    		}
    }
    IL void add(int u,int op){for(int i=0;i<v[a[u]].size();++i) sum[v[a[u]][i]]+=op*dep[u],c[v[a[u]][i]]+=op;}
    IL void Add(int u,int fa,int op){
    	add(u,op);
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^fa) Add(v,u,op);
    }
    void calc(int u,int fa,int x){
    	for(int i=0;i<v[a[u]].size();++i) 
    	  ans+=(cc[v[a[u]][i]]&1?-1:1)*(sum[v[a[u]][i]]+1ll*(dep[u]-2*dep[x])*c[v[a[u]][i]]);
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^fa) calc(v,u,x);
    }
    void dfs2(int u,int fa,int op){
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^fa&&v^son[u]) dfs2(v,u,1);
    	if(son[u]) dfs2(son[u],u,0);
    	for(int i=0;i<v[a[u]].size();++i)
    	  ans+=(cc[v[a[u]][i]]&1?-1:1)*(sum[v[a[u]][i]]-1ll*c[v[a[u]][i]]*dep[u]);
    	add(u,1);
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^fa&&v^son[u]) calc(v,u,u),Add(v,u,1);
    	if(op) Add(u,fa,-1);
    }
    int main()
    {
    	int x,y;
    	init(),n=in();
    	for(int i=1;i<=n;++i) a[i]=vv[in()];
    	for(int i=1;i<n;++i)
    	  x=in(),y=in(),
    	  ini(x,y),ini(y,x);
    	dfs1(1,0),dfs2(1,0,0);
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    树上的树

    子树差分,树剖做法有点类似于动态dp。

    #include<bits/stdc++.h>
    #define IL inline
    #define LL long long
    #define pb push_back
    using namespace std;
    const int N=1e6+3;
    struct hh{
    	int to,nxt;
    }e[N<<1];
    struct kk{
    	int to,id;
    };
    int n,m,fir[N],num,fa[N],st[N],ed[N],vis[N];
    int X[N],Y[N],w[N];
    LL f[N];int  val[N];
    vector<int>pi[N];
    vector<kk>p[N];
    struct BIT{
    	LL c[N];
    	IL int lb(int x){return x&-x;}
    	IL void add(int y,LL x){for(;y<=n;y+=lb(y)) c[y]+=x;}
    	IL LL ask(int y){LL res=0;for(;y;y-=lb(y)) res+=c[y];return res;}
    }T;
    IL int in(){
    	char c;int f=1;
    	while((c=getchar())<'0'||c>'9')
    	  if(c=='-') f=-1;
    	int x=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    	  x=x*10+c-'0';
    	return x*f;
    }
    IL LL max(LL x,LL y){return x>y?x:y;}
    IL void add(int x,int y){e[++num]=(hh){y,fir[x]},fir[x]=num;}
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void dfs1(int u,int fa){
    	st[u]=++num;
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(v^fa) dfs1(v,u);
    	ed[u]=num;
    }
    void dfs2(int u){
    	LL Sum=0,res=0;vis[u]=1;
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(!vis[v]) dfs2(v),Sum+=f[v],fa[v]=u;
    	for(int i=0,v;i<p[u].size();++i)
    	  if(vis[v=p[u][i].to]==2) pi[find(v)].pb(p[u][i].id);
    	T.add(st[u],Sum);
    	for(int i=fir[u],v;v=e[i].to;i=e[i].nxt)
    	  if(vis[v]==2) T.add(st[v],res-f[v]),res=f[v];
    	T.add(ed[u]+1,res-Sum);
    	for(int i=0,v;i<pi[u].size();++i){
    		v=pi[u][i];
    		f[u]=max(f[u],T.ask(st[X[v]])+T.ask(st[Y[v]])+w[v]-Sum);
    	}
    	f[u]=max(f[u],Sum+val[u]);
    	vis[u]=2;
    }
    signed main()
    {
    	int x,y,z;
    	n=in(),m=in();
    	for(int i=1;i<=n;++i) fa[i]=i;
    	for(int i=1;i<n;++i)
    	  x=in(),y=in(),
    	  add(x,y),add(y,x);
    	num=0,dfs1(1,0);
    	for(int i=1;i<=m;++i){
    		X[i]=in(),Y[i]=in(),w[i]=in();
    		if(X[i]==Y[i]) val[X[i]]=max(val[X[i]],w[i]);
    		else p[X[i]].pb((kk){Y[i],i}),p[Y[i]].pb((kk){X[i],i});
    	}
    	dfs2(1);
    	printf("%lld
    ",f[1]);
    	return 0;
    }
    
  • 相关阅读:
    全新的ASP.NET !
    asp.net core+ef core
    直播服务器Nginx
    NET Core1
    网络爬虫1
    java thread reuse(good)
    java中Executor、ExecutorService、ThreadPoolExecutor介绍(转)
    小心LinkedHashMap的get()方法(转)
    LinkedHashMap相关信息介绍(转)
    HashTable和HashMap的区别
  • 原文地址:https://www.cnblogs.com/yiqiAtiya/p/13914180.html
Copyright © 2011-2022 走看看