zoukankan      html  css  js  c++  java
  • bzoj 4719: [Noip2016]天天爱跑步【树上差分+dfs】

    长久以来的心理阴影?但是其实非常简单……
    预处理出deep和每组st的lca,在这里我简单粗暴的拿树剖爆算了
    然后考虑对于一组s t lca来说,被这组贡献的观察员x当且仅当:
    x在s到lca的路径上,且w[x]de[s]-de[x]——>de[x]+w[x]de[s];
    x在lca到t的路径上,且w[x]de[x]-de[lca]+de[s]-de[lca]——>de[x]-w[x]de[s]-2de[lca];
    然后把这一段拆成四个点(树上差分),一遍dfs统计状态即可
    注意,因为w==0时答案会被统计两遍,所以要除二
    可是我居然因为数组大小多用了1h???我怕不是个zz

    #include<iostream>
    #include<cstdio>
    #include<vector>
    using namespace std;
    const int N=600005;
    int n,m,h[N],cnt,w[N],s[N],t[N],de[N],fa[N],si[N],fr[N],hs[N],lc[N],d[N],ans[N];
    struct qwe
    {
    	int ne,to;
    }e[N<<1];
    struct tg
    {
    	int p,c;
    	tg(int P=0,int C=0)
    	{
    		p=P,c=C;
    	}
    };
    vector<tg>a[N];
    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)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].to=v;
    	h[u]=cnt;
    }
    void dfs1(int u,int fat)
    {
    	si[u]=1;
    	fa[u]=fat;
    	de[u]=de[fat]+1;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fat)
    		{
    			dfs1(e[i].to,u);
    			si[u]+=si[e[i].to];
    			if(si[e[i].to]>si[hs[u]])
    				hs[u]=e[i].to;
    		}
    }
    void dfs2(int u,int top)
    {
    	fr[u]=top;
    	if(!hs[u])
    		return;
    	dfs2(hs[u],top);
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa[u]&&e[i].to!=hs[u])
    			dfs2(e[i].to,e[i].to);
    }
    int lca(int u,int v)
    {
    	for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);
    	return de[u]<de[v]?u:v;
    }
    void dfs(int u)
    {
    	int x=d[de[u]+w[u]],y=d[de[u]-w[u]];
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=fa[u])
    			dfs(e[i].to);
    	for(int i=0;i<a[u].size();i++)
    		d[a[u][i].p]+=a[u][i].c;
    	ans[u]+=d[de[u]+w[u]]-x+d[de[u]-w[u]]-y;
    	if(!w[u])
    		ans[u]/=2;
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<n;i++)
    	{
    		int x=read(),y=read();
    		add(x,y),add(y,x);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	for(int i=1;i<=n;i++)
    		w[i]=read();
    	for(int i=1;i<=m;i++)
    		s[i]=read(),t[i]=read(),lc[i]=lca(s[i],t[i]);
    	for(int i=1;i<=m;i++)
    	{
    		int l=lc[i],du=de[s[i]],dv=de[t[i]],dl=de[l],dis=du+dv-2*dl;
    		a[s[i]].push_back(tg(du,1));
    		a[l].push_back(tg(du,-1));
    		a[t[i]].push_back(tg(dv-dis,1));
    		a[fa[l]].push_back(tg(dv-dis,-1));
    	}
    	dfs(1);
    	for(int i=1;i<=n;i++)
    		printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    metal的gpu query
    体积雾 global fog unity 及改进
    hdr rt format对颜色的影响
    unity deferred lighting
    unity linear space时 photoshop blend的正确设置
    unity linear work flow
    一些数据 bandwidth之类
    deferred rendering with msaa
    unity 显示mipmaplevel
    【转】在C#中使用SendMessage
  • 原文地址:https://www.cnblogs.com/lokiii/p/9368608.html
Copyright © 2011-2022 走看看