zoukankan      html  css  js  c++  java
  • 联考20200718 T1 因懒无名

    题目描述:


    分析:
    签到题想半天,人没了
    将两个点集合并维护直径,两个点集分别的直径一共四个端点两两距离最大即为直径
    区间点集合并,联想到线段树,每个区间两个值表示这个区间点集合并出的端点,简单维护
    考虑颜色变化导致的点集内部插入删除
    加入很好维护,删除不行
    每种颜色动态开点线段树,依葫芦画瓢维护
    巨佬们说可以直接一发平衡树,按颜色排序,支持插入删除,维护区间直径
    好像Splay和非旋Treap都可以维护
    也是可以做的,只不过我平衡树太菜了,写的动态开点
    我的复杂度是\(O(nlog^2n)\),写了\(O(1)\)求LCA深度之后就可以减到\(O(nlogn)\)
    (怎么我\(O(nlog^2n)\)比写\(O(nlogn)\)的平衡树快啊2333

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    #include<string>
    
    #define maxn 200005
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,m,Q;
    int fir[maxn],nxt[maxn<<1],to[maxn<<1],cnt;
    int sz[maxn],fa[maxn],dpt[maxn],son[maxn],tp[maxn];
    int C[maxn],rt[maxn],tot;
    int lc[maxn<<6],rc[maxn<<6];
    
    inline void newnode(int u,int v)
    {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    inline void dfs1(int u)
    {
    	sz[u]=1;
    	for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa[u])
    	{
    		fa[to[i]]=u,dpt[to[i]]=dpt[u]+1;
    		dfs1(to[i]),sz[u]+=sz[to[i]];
    		if(sz[son[u]]<sz[to[i]])son[u]=to[i];
    	}
    }
    inline void dfs2(int u,int ac)
    {
    	tp[u]=ac;if(son[u])dfs2(son[u],ac);
    	for(int i=fir[u];i;i=nxt[i])if(to[i]!=fa[u]&&to[i]!=son[u])dfs2(to[i],to[i]);
    }
    inline int LCA(int u,int v)
    {
    	while(tp[u]!=tp[v])
    	{
    		if(dpt[tp[u]]<dpt[tp[v]])swap(u,v);
    		u=fa[tp[u]];
    	}
    	return dpt[u]<dpt[v]?u:v;
    }
    inline int getdis(int u,int v)
    {return dpt[u]+dpt[v]-2*dpt[LCA(u,v)];}
    
    struct node{
    	int A,B;
    	inline void pushup(node x,node y)
    	{
    		if(!x.A||!y.A){A=x.A|y.A,B=x.B|y.B;return;}
    		int mx=-1,tmp;
    		if((tmp=getdis(x.A,x.B))>mx)mx=tmp,A=x.A,B=x.B;
    		if((tmp=getdis(y.A,y.B))>mx)mx=tmp,A=y.A,B=y.B;
    		if((tmp=getdis(x.A,y.A))>mx)mx=tmp,A=x.A,B=y.A;
    		if((tmp=getdis(x.A,y.B))>mx)mx=tmp,A=x.A,B=y.B;
    		if((tmp=getdis(x.B,y.A))>mx)mx=tmp,A=x.B,B=y.A;
    		if((tmp=getdis(x.B,y.B))>mx)mx=tmp,A=x.B,B=y.B;
    	}
    }t[maxn<<2],p[maxn<<6],Ans;
    
    inline void insert(int &i,int l,int r,int x,int num)
    {
    	if(!i)i=++tot;
    	if(l==r){p[i].A=p[i].B=num;return;}
    	int mid=(l+r)>>1;
    	if(x<=mid)insert(lc[i],l,mid,x,num);
    	else insert(rc[i],mid+1,r,x,num);
    	p[i].pushup(p[lc[i]],p[rc[i]]);
    }
    inline void build(int i,int l,int r)
    {
    	if(l==r){t[i]=p[rt[l]];return;}
    	int mid=(l+r)>>1;
    	build(i<<1,l,mid),build(i<<1|1,mid+1,r);
    	t[i].pushup(t[i<<1],t[i<<1|1]);
    }
    inline void update(int i,int l,int r,int x)
    {
    	if(l==r){t[i]=p[rt[x]];return;}
    	int mid=(l+r)>>1;
    	if(x<=mid)update(i<<1,l,mid,x);
    	else update(i<<1|1,mid+1,r,x);
    	t[i].pushup(t[i<<1],t[i<<1|1]);
    }
    inline void query(int i,int l,int r,int ql,int qr)
    {
    	if(qr<l||r<ql)return;
    	if(ql<=l&&r<=qr){Ans.pushup(Ans,t[i]);return;}
    	int mid=(l+r)>>1;
    	query(i<<1,l,mid,ql,qr),query(i<<1|1,mid+1,r,ql,qr);
    }
    
    int main()
    {
    	n=getint(),m=getint(),Q=getint();
    	for(int i=1;i<=n;i++)C[i]=getint();
    	for(int i=1;i<n;i++)
    	{
    		int u=getint(),v=getint();
    		newnode(u,v),newnode(v,u);
    	}
    	dfs1(1),dfs2(1,1);
    	for(int i=1;i<=n;i++)insert(rt[C[i]],1,n,i,i);
    	build(1,1,m);
    	while(Q--)
    	{
    		int op=getint(),x=getint(),y=getint();
    		if(op==1)
    		{
    			insert(rt[C[x]],1,n,x,0);
    			update(1,1,m,C[x]);
    			C[x]=y;
    			insert(rt[C[x]],1,n,x,x);
    			update(1,1,m,C[x]);
    		}
    		else
    		{
    			Ans.A=Ans.B=0;
    			query(1,1,m,x,y);
    			printf("%d\n",Ans.A?getdis(Ans.A,Ans.B):0);
    		}
    	}
    }
    

  • 相关阅读:
    BiliBili, ACFun… And More!【递归算法】
    【VS2015】关于VS2015如何运行的问题
    【打死树莓派】-树莓派3代jessie+Opencv-解决安装不了libgtk2.0-dev包问题
    插入排序2.0
    【C++小白成长撸】--(续)单偶数N阶魔方矩阵
    【C++小白成长撸】--(续)双偶数N阶魔阵
    安装 python-opencv
    二叉树打印
    Kotlin接口
    Kotlin 继承
  • 原文地址:https://www.cnblogs.com/IzayoiDoyo/p/13336206.html
Copyright © 2011-2022 走看看