zoukankan      html  css  js  c++  java
  • bzoj 1827: [Usaco2010 Mar]gather 奶牛大集会【树形dp】

    不能用read会TLE!!不能用read会TLE!!不能用read会TLE!!
    一开始以为要维护每个点,线段树写了好长(还T了……
    首先dfs一遍,求出点1为集会地点的答案,处理处val[u]为以1为根u子树点权和
    然后从1带着当前点答案ans跑dfs,向儿子转移的时候就是带下去儿子的ans'就是ans-val[e[i].to]*e[i].va+(val[1]-val[e[i].to])*e[i].va

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=1000005;
    int n,a[N],h[N],cnt;
    long long ans,val[N];
    struct qwe
    {
    	int ne,to,va;
    }e[N<<1];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    void pre(int u,int fa,int len)
    {
    	val[u]=a[u],ans+=len*val[u];
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa)
    		{
    			pre(e[i].to,u,len+e[i].va);
    			val[u]+=val[e[i].to];
    		}
    }
    void dfs(int u,int fa,long long va)
    {
    	ans=min(ans,va);//cerr<<u<<" "<<va<<endl;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa)
    			dfs(e[i].to,u,ans-val[e[i].to]*e[i].va+(val[1]-val[e[i].to])*e[i].va);
    }
    int main()
    {
    	scanf("%d",&n);//n=read();
    	for(int i=1;i<=n;i++)
    		scanf("%d",&a[i]);//a[i]=read();
    	for(int i=1;i<n;i++)
    	{
    		int x,y,z;//int x=read(),y=read(),z=read();
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z),add(y,x,z);
    	}
    	pre(1,0,0);
    	dfs(1,0,ans);
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    顺便把T了的线段树也放上来吧毕竟写了好久……

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=1000005;
    int n,a[N],h[N],cnt,in[N],out[N],tmp,rl[N];
    long long ans=1e18,dis[N];
    struct qwe
    {
    	int ne,to,va;
    }e[N<<1];
    struct xds
    {
    	int l,r;
    	long long len,val,sum,lz;
    }t[N*3];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	e[cnt].va=w;
    	h[u]=cnt;
    }
    void pre(int u,int fa,int len)
    {
    	dis[u]=len;
    	in[u]=++tmp,rl[tmp]=u;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa)
    			pre(e[i].to,u,len+e[i].va);
    	out[u]=tmp;
    }
    inline void pd(int ro)
    {
    	if(t[ro].lz!=0)
    	{
    		t[ro<<1].sum+=t[ro<<1].val*t[ro].lz;
    		t[ro<<1].lz+=t[ro].lz;
    		t[ro<<1|1].sum+=t[ro<<1|1].val*t[ro].lz;
    		t[ro<<1|1].lz+=t[ro].lz;
    		t[ro].lz=0;
    	}
    }
    void build(int ro,int l,int r)
    {
    	t[ro].l=l,t[ro].r=r;
    	if(l==r)
    	{
    		t[ro].len=dis[rl[l]];
    		t[ro].val=a[rl[l]];
    		t[ro].sum=a[rl[l]]*dis[rl[l]];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ro<<1,l,mid);
    	build(ro<<1|1,mid+1,r);
    	t[ro].val=t[ro<<1].val+t[ro<<1|1].val;
    	t[ro].sum=t[ro<<1].sum+t[ro<<1|1].sum;
    }
    void update(int ro,int l,int r,long long v)
    {//cerr<<l<<" "<<r<<"   "<<t[ro].l<<" "<<t[ro].r<<endl;
    	if(r<l)
    		return;
    	if(t[ro].l==l&&t[ro].r==r)
    	{
    		t[ro].sum+=t[ro].val*v;
    		t[ro].lz+=v;
    		return;
    	}
    	pd(ro);
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		update(ro<<1,l,r,v);
    	else if(l>mid)
    		update(ro<<1|1,l,r,v);
    	else
    		update(ro<<1,l,mid,v),update(ro<<1|1,mid+1,r,v);
    	t[ro].sum=t[ro<<1].sum+t[ro<<1|1].sum;
    }
    void dfs(int u,int fa)
    {
    	ans=min(ans,t[1].sum);//cerr<<u<<" "<<t[1].sum<<endl;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa)
    		{
    			update(1,in[e[i].to],out[e[i].to],-e[i].va);
    			update(1,1,in[e[i].to]-1,e[i].va);
    			update(1,out[e[i].to]+1,n,e[i].va);
    			dfs(e[i].to,u);
    			update(1,in[e[i].to],out[e[i].to],e[i].va);
    			update(1,1,in[e[i].to]-1,-e[i].va);
    			update(1,out[e[i].to]+1,n,-e[i].va);
    		}
    }
    int main()
    {
    	scanf("%d",&n);//n=read();
    	for(int i=1;i<=n;i++)
    		scanf("%d",&a[i]);//a[i]=read();
    	for(int i=1;i<n;i++)
    	{
    		int x,y,z;//int x=read(),y=read(),z=read();
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z),add(y,x,z);
    	}
    	pre(1,0,0);
    	build(1,1,n);
    	dfs(1,0);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    18.centos7基础学习与积累-004-分区理论
    绑定省份到select控件
    c#编写1-2+3-4……m
    在写按时间段查询的sql语句的时候 一般我们会这么写查询条件:
    二进制移位运算
    构造datatable临时数据
    svn代表四种检出深度
    关于TTS SpeechVoiceSpeakFlags几个值的中文意思?
    user32.dll中的所有函数
    xaml 微软帮助 url
  • 原文地址:https://www.cnblogs.com/lokiii/p/8986431.html
Copyright © 2011-2022 走看看