• SPOJ QTREE Query on a tree V ——动态点分治


    【题目分析】

        QTREE4的弱化版本

        建立出分治树,每个节点的堆表示到改点的最近白点距离。

        然后分治树上一直向上,取min即可。

        正确性显然,不用担心出现在同一子树的情况(不会是最优解),请自行脑补。

        然后弱渣我写了1.5h

    【代码】

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define inf 0x3f3f3f3f
    #define maxe 200005
    #define maxn 100005
    struct Heap{
    	priority_queue<int, vector<int>, greater<int> > heap,del;
    	void Ins(int x){heap.push(x);}
    	void Del(int x){del.push(x);}
    	int Size(){return heap.size()-del.size();}
    	int Top(){while (del.size()&&heap.top()==del.top()) heap.pop(),del.pop();return heap.top();}
    }s[maxn];
    
    int h[maxe],to[maxe],ne[maxe],en=0,n,m,_log[maxn<<2],a[maxn<<2][20],col[maxn],tag=0,x;
    int siz[maxn],mx[maxn],root,now,b[maxn<<2],top=0,pos[maxn],size,ban[maxn],T_rt,dst[maxn],fa[maxn];
    
    void add(int a,int b){to[en]=b;ne[en]=h[a];h[a]=en++;}
    
    void dfs(int o,int fa)
    {
    	siz[o]=1; mx[o]=0;
    	if (!tag) b[++top]=o,pos[o]=top;
    	for (int i=h[o];i>=0;i=ne[i])
    		if (!ban[to[i]]&&to[i]!=fa)
    		{
    			dfs(to[i],o);
    			if (!tag) b[++top]=o;
    			siz[o]+=siz[to[i]];
    			mx[o]=max(mx[o],siz[to[i]]);
    		}
    }
    
    void dfs_root(int o,int fa)
    {
    	if (now>max(mx[o],size-siz[o])) root=o,now=max(mx[o],size-siz[o]);
    	for (int i=h[o];i>=0;i=ne[i])
    		if (!ban[to[i]]&&to[i]!=fa)
    			dfs_root(to[i],o);
    }
    
    void dfs_dist(int o,int fa)
    {
    	for (int i=h[o];i>=0;i=ne[i])
    		if (!ban[to[i]]&&to[i]!=fa)
    			dst[to[i]]=dst[o]+1,dfs_dist(to[i],o);
    }
    
    void Divide(int o,int fat)
    {
    	dfs(o,-1);now=inf;size=siz[o];dfs_root(o,-1);
    	int rt=root; ban[rt]=1;fa[rt]=fat;
    	for (int i=h[rt];i>=0;i=ne[i])
    		if (!ban[to[i]]) Divide(to[i],rt);
    }
    
    int dist(int x,int y)
    {
    	int ret=dst[x]+dst[y];
    	x=pos[x],y=pos[y];
    	if (x>y) swap(x,y);
    	int l=_log[y-x+1];
    	return ret-2*min(a[x][l],a[y-(1<<l)+1][l]);
    }
    
    void Delete(int o)
    {
    	s[o].Del(0);
    	int now=fa[o];
    	while (now)
    	{
    		s[now].Del(dist(o,now));
    		now=fa[now];
    	}
    }
    
    void Insert(int o)
    {
    	s[o].Ins(0);
    	int now=fa[o];
    	while (now)
    	{
    		s[now].Ins(dist(o,now));
    		now=fa[now];
    	}
    }
    
    int query(int o)
    {
    	int ret=inf;
    	if (s[o].Size()) ret=min(ret,s[o].Top());
    	int now=fa[o];
    	while (now)
    	{
    		if (s[now].Size()) ret=min(s[now].Top()+dist(o,now),ret);
    		now=fa[now];
    	}
    	if (ret==inf) printf("-1
    ");
    	else printf("%d
    ",ret);
    }
    
    int main()
    {
    	memset(h,-1,sizeof h);
    	scanf("%d",&n);
    	F(i,1,n-1)
    	{
    		int a,b;
    		scanf("%d%d",&a,&b);
    		add(a,b);add(b,a);
    	}
    	tag=1; dfs(1,-1); size=siz[1]; now=inf; dfs_root(1,-1); T_rt=root;
    	tag=0; dfs(root,-1); dfs_dist(root,-1); tag=1;
    	F(i,2,top) _log[i]=_log[i>>1]+1;
    	F(i,1,top) a[i][0]=dst[b[i]];
    	F(j,1,_log[top])
    		for (int i=1;i+(1<<j)-1<=top;++i)
    			a[i][j]=min(a[i][j-1],a[i+(1<<j-1)][j-1]);
    	Divide(T_rt,0);
    	scanf("%d",&m);
    	F(i,1,m)
    	{
    		int opt; scanf("%d",&opt);
    		switch(opt)
    		{
    			case 0:scanf("%d",&x);if (col[x]) Delete(x); else Insert(x); col[x]^=1; break;
    			case 1:scanf("%d",&x);query(x); break;
    		}
    	}
    }
    

      

  • 相关阅读:
    在am中定义消息集束,并在CO中验证之后抛出异常。
    在EORow或者VORow中对数据进行重复性校验
    axis2 webservice jar包使用情况(转)
    std::function以及std::bind
    Qt学习过程
    NULL和nullptr
    清空表且id为0
    C++线程互斥、同步
    warning: deleting 'void *' is undefined 错误
    Classification / Recognition
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6417438.html
Copyright © 2020-2023  润新知