zoukankan      html  css  js  c++  java
  • SP2939 QTREE5

    SP2939 QTREE5 - Query on a tree V解题报告:

    更好的阅读体验

    题意

    给定一棵 (n) 各点原始全白的树,(m) 次操作,支持单点颜色翻转以及查询一个点距离最近的黑点的距离。

    (1leqslant n,mleqslant 10^5)

    分析

    模拟赛题,好像有个简单的点分树写法,不过操作分块也可以轻松解决。(类似 CF342E

    对于修改操作,你直接维护单点的颜色;查询分为两部分:本块之前修改的点(本快操作中一定不存在修改),本块修改过的点、

    第一部分可以直接在每个块结束后维护出每个点距离这样的点的最短距离(bfs),第二部分则可以枚举点求距离直接判断。

    用了 (O(nlog n)-O(1)) 的 lca,时间复杂度 (O((n+m)sqrt m))

    代码

    #include<stdio.h>
    #include<math.h>
    #include<vector>
    #define inf 1000000000
    using namespace std;
    const int maxn=100005,maxm=200005,maxk=20,maxq=100005;
    int n,m,e,S,T,now,qs;
    int start[maxn],to[maxm],then[maxm],lg[maxn<<1],ST[maxn<<1][maxk],dep[maxn],in[maxn],bl[maxn],br[maxn],opt[maxq],k[maxq],dis[maxn],q[maxn],col[maxn],ok[maxn];
    inline int calc(int a,int b){
    	return dep[a]<dep[b]? a:b;
    }
    inline void add(int x,int y){
    	then[++e]=start[x],start[x]=e,to[e]=y;
    }
    void dfs(int x,int last){
    	dep[x]=dep[last]+1,in[x]=++qs,ST[qs][0]=x;
    	for(int i=start[x];i;i=then[i]){
    		int y=to[i];
    		if(y==last)
    			continue;
    		dfs(y,x);
    		ST[++qs][0]=x;
    	}
    }
    void getST(){
    	lg[0]=-1;
    	for(int i=1;i<=qs;i++)
    		lg[i]=lg[i/2]+1;
    	for(int i=1;i<=18;i++)
    		for(int j=1;j+(1<<i)-1<=qs;j++)
    			ST[j][i]=calc(ST[j][i-1],ST[j+(1<<(i-1))][i-1]);
    }
    int lca(int a,int b){
    	if(in[a]>in[b])
    		swap(a,b);
    	int l=in[a],r=in[b],k=lg[r-l+1];
    	return calc(ST[l][k],ST[r-(1<<k)+1][k]);
    }
    int getdis(int a,int b){
    	return dep[a]+dep[b]-2*dep[lca(a,b)];
    }
    void bfs(int a,int b,int c,int d){
    	int hd=1,tl=0;
    	if(c)
    		for(int i=c;i<=d;i++)
    			if(opt[i]==1)
    				ok[k[i]]=1;
    	for(int i=1;i<=n;i++){
    		if(col[i]==1&&ok[i]==0)
    			q[++tl]=i,dis[i]=0;
    		else dis[i]=inf;
    		ok[i]=0;
    	}
    	while(hd<=tl){
    		int x=q[hd++];
    		for(int i=start[x];i;i=then[i])
    			if(dis[to[i]]>dis[x]+1)
    				dis[to[i]]=dis[x]+1,q[++tl]=to[i];
    	}
    }
    int query(int x,int a,int b,int c){
    	int res=dis[x];
    	if(col[x])
    		res=0;
    	for(int i=a;i<=c;i++)
    		if(opt[i]==1&&col[k[i]]==1)
    			res=min(res,getdis(x,k[i]));
    	return res==inf? -1:res;
    }
    void read(int &x){
    	char c=getchar();
    	x=0;
    	for(;c<'0'||c>'9';c=getchar());
    	for(;c>='0'&&c<='9';c=getchar())
    		x=x*10+c-48;
    }
    int main(){
    	read(n);
    	for(int i=1,x,y;i<n;i++)
    		read(x),read(y),add(x,y),add(y,x);
    	read(m);
    	dfs(1,0),getST(),S=800,T=m/S;
    	for(int i=1;i<=T;i++)
    		bl[i]=br[i-1]+1,br[i]=i*S;
    	if(br[T]<m)
    		T++,bl[T]=bl[T-1]+1,br[T]=m;
    	for(int i=1;i<=n;i++)
    		dis[i]=inf;
    	for(int i=1;i<=m;i++)
    		read(opt[i]),read(k[i]),opt[i]++;
    	for(int i=1,lst=1;i<=m;i++){
    		if(i>br[lst])
    			bfs(bl[lst],br[lst],bl[lst+1],br[lst+1]),lst++;
    		if(opt[i]==1)
    			col[k[i]]^=1;
    		if(opt[i]==2)
    			printf("%d
    ",query(k[i],bl[lst],i,br[lst]));
    	}
    	return 0;
    }
    
  • 相关阅读:
    深入浅出进程与线程的基本概念
    python中with的用法
    浮点型数据在内存中存储的表示
    自问问题列表以及网络答案整理
    看java源代码
    【设计模式】工厂方法
    SQL实现递归及存储过程中 In() 参数传递解决方案
    app与server联系
    添加service到SystemService硬件服务
    noproguard.classes-with-local.dex
  • 原文地址:https://www.cnblogs.com/xiaoziyao/p/15370893.html
Copyright © 2011-2022 走看看