zoukankan      html  css  js  c++  java
  • 题解 P3258 【[JLOI2014]松鼠的新家】(From luoguBlog)

    唯一能得分的题也被自己搞炸了,好的。

    考场上读完题基本认定和lca脱不了干系,想了一会确认是树剖。

    那么问题来了,考前一节课刚发现自己之前打的树剖是错的。

    而且就算是错的我也没信心考场调出来。

    于是打了个自认为复杂度不高的暴力,T出天际,被各位不屑于打树剖的巨佬の向上标记干趴下。

    考完翻书学了一下树上差分,赶脚不错。

    树剖||Tarjan求lca+树上差分

    后者的思路是预处理路线上每两个房间的lca

    每次num[x]++,num[y]++,num[lca]++,num[father[lca]]++

    最后进行一次dfs统计所有点的权值

    int dfs(int x)
    {
    	v[x]=1;int now=0;
    	for(int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(v[y])continue;
    		now+=dfs(y);
    	}
    	num[x]+=now;
    	return num[x];
    }
    

    最后num[way[1]]++
    然后输出way[i]-1 (因为除了第一个点之外的每个点都算了两遍)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int N=300010;
    int n;
    int to[N<<1],nxt[N<<1],num[N],tot=0,fa[N],v[N],root,head[N],ans[N],way[N],father[N];
    vector<int> q[N],qi[N];
    void add(int x,int y)
    {
    	to[++tot]=y;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    void insq(int x,int y,int i)
    {
    	q[x].push_back(y);
    	qi[x].push_back(i);
    	q[y].push_back(x);
    	qi[y].push_back(i);
    }
    int getf(int x)
    {
    	if(x==fa[x])return x;
    	fa[x]=getf(fa[x]);
    	return fa[x];
    }
    void tarjan(int x)
    {
    	v[x]=1;
    	for(int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(v[y])continue;
    		tarjan(y);
    		fa[y]=father[y]=x;
    	}
    	for(int i=0;i<q[x].size();i++)
    	{
    		int y=q[x][i],id=qi[x][i];
    		if(v[y]==2)ans[id]=getf(y);
    	}
    	v[x]=2;
    }
    int dfs(int x)
    {
    	v[x]=1;int now=0;
    	for(int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(v[y])continue;
    		now+=dfs(y);
    	}
    	num[x]+=now;
    	return num[x];
    }
    int main()
    {
    	/*freopen("FU.in","r",stdin);
    	freopen("FU.out","w",stdout);*/
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&way[i]),fa[i]=i;
    	root=way[1];
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);add(y,x);
    		x=way[i],y=way[i+1];
    		insq(x,y,i);
    	}
    	/*cout<<endl;
    	for(int i=1;i<=n;i++)cout<<father[i]<<' ';
    	cout<<endl;*/
    	tarjan(root);
    	memset(v,0,sizeof(v));
    	for(int i=1;i<n;i++)
    	{
    		int x=way[i],y=way[i+1],lca=ans[i];
    		num[x]++;num[y]++;num[lca]--;num[father[lca]]--;
    	}
    	dfs(root);
    	num[root]++;
    	for(int i=1;i<=n;i++)printf("%d
    ",num[i]-1);
    	return 0;
    }
    
    兴许青竹早凋,碧梧已僵,人事本难防。
  • 相关阅读:
    iOS开发 贝塞尔曲线UIBezierPath
    iOS开发 解决使用AVAudioRecorder录制后转mp3解决音量小的问题
    比JDK高效的array equals
    高性能web架构原则
    基于内存映射的千万级数据处理框架
    LesenRPC-基于netty/protobuffer的高性能RPC框架
    java垃圾回收机制详解
    MVC架构详解
    用抽象实现代码解耦
    python按年份统计文件数量
  • 原文地址:https://www.cnblogs.com/Rorschach-XR/p/10969181.html
Copyright © 2011-2022 走看看