zoukankan      html  css  js  c++  java
  • Codeforces 1083C Max Mex 线段树

    题意

    给出一棵(n)个节点,以(1)为根的树。

    每个节点都有一个权值(v_i)(v_i in [0,n-1])且没有两个节点的(v_i)相同。

    定义(V)为树上某条路径上的节点的(v_i)组成的集合。

    给出(q)次操作,每次交换两个节点的(v_i)或者询问所有可能的(V)(mex)(max)

    Solution

    看到(v_i)互不相同,肯定就想到先转化一下。

    首先设(pos_i)为权值为(i)的节点的编号。

    那么每次询问的答案就是找一个最大的(k)满足,(pos_i(i in [0,k)))在同一条链上。

    考虑线段树来维护这个东西。

    线段树上每个节点维护一个数对((x,y)),如果这个区间内节点不在同一个链上这个数对就是((-1,-1)),否则就是这些节点所在的那条链的两端。

    合并左右儿子信息的时候,如果其中有一个((-1,-1))则当前节点肯定也是((-1,-1)),否则当前这个区间的节点所在的那条链的两端肯定是左右儿子的((x,y))其中的两个数,暴力一波就行了。

    #include<bits/stdc++.h>
    #define For(i,x,y) for (register int i=(x);i<=(y);i++)
    #define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
    #define cross(i,k) for (register int i=first[k];i;i=last[i])
    #define Debug(x) cerr<<#x<<"="<<(x)<<endl
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pa;
    inline ll read(){
        ll x=0;int ch=getchar(),f=1;
        while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
        if (ch=='-'){f=-1;ch=getchar();}
        while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    namespace Fuck{ 
    	const int N = 2e5+10;
    	int n,q,a[N],fa[N],pos[N];
    	int tot,first[N],to[N<<1],last[N<<1];
    	inline void Add(int x,int y){to[++tot]=y,last[tot]=first[x],first[x]=tot;}
    	int cnt,size[N],son[N],dep[N];
    	inline void dfs(int u){
    		size[u]=1,dep[u]=dep[fa[u]]+1;
    		cross(i,u){
    			dfs(to[i]),size[u]+=size[to[i]];
    			son[u]=size[to[i]]>size[son[u]]?to[i]:son[u];
    		}
    	}
    	int t[N],l[N];
    	inline void dfs(int u,int Top){
    		l[u]=++cnt,t[u]=Top;
    		if (son[u]) dfs(son[u],Top);
    		cross(i,u) if (to[i]!=son[u]) dfs(to[i],to[i]);
    	}
    	inline int Lca(int x,int y){
    		for (;t[x]!=t[y];x=fa[t[x]]) if (dep[t[x]]<dep[t[y]]) swap(x,y);
    	    return dep[x]<dep[y]?x:y;
    	}
    	inline bool In(int x,int y){return l[x]<=l[y]&&l[y]<=l[x]+size[x]-1;}//y in x?
    	int tmp[4];
    	inline pa operator + (const pa &a,const pa &b){
    		tmp[0]=a.fi,tmp[1]=a.se,tmp[2]=b.fi,tmp[3]=b.se;
    		For(i,0,3) if (tmp[i]==-1) return mp(-1,-1);
    		if (tmp[1]==tmp[2]&&tmp[2]==tmp[3]&&tmp[0]==tmp[1]) return mp(tmp[0],tmp[1]);
    		For(i,0,3)
    			For(j,i+1,3){
    				if (tmp[i]==tmp[j]) continue;
    				int lca=Lca(tmp[i],tmp[j]),flag=1;
    				For(k,0,3)
    					if (k!=i&&k!=j)
    						if (!In(lca,tmp[k])||(In(lca,tmp[k])&&!(In(tmp[k],tmp[i])||In(tmp[k],tmp[j])))){flag=0;break;}
    				if (flag) return mp(tmp[i],tmp[j]);
    			}
    		return mp(-1,-1);
    	}
    	pa v[N<<2];
    	inline void push_up(int u){v[u]=v[u<<1]+v[u<<1^1];}
    	inline void Build(int u,int l,int r){
    		if (l==r){v[u]=l==n+1?mp(-1,-1):mp(pos[l],pos[l]);return;}int mid=l+r>>1;
    		Build(u<<1,l,mid),Build(u<<1^1,mid+1,r),push_up(u);
    	}	
    	inline void update(int u,int l,int r,int ql){
    		if (l==r){v[u]=mp(pos[l],pos[l]);return;}
    		int mid=l+r>>1;(ql<=mid)?update(u<<1,l,mid,ql):update(u<<1^1,mid+1,r,ql);
    		push_up(u);
    	}
    	inline int Query(int u,int l,int r,pa x){
    		if (l==r) return l;
    		int mid=l+r>>1;pa tmp=x+v[u<<1];
    		if (tmp.fi!=-1) return Query(u<<1^1,mid+1,r,tmp);
    			else return Query(u<<1,l,mid,x);
    	}
    	inline void Main(){
    		n=read();
    		For(i,1,n) a[i]=read()+1,pos[a[i]]=i;
    		For(i,2,n) fa[i]=read(),Add(fa[i],i);
    		dfs(1),dfs(1,1),Build(1,1,n+1),q=read();
    		while (q--){
    			int opt=read();
    			if (opt==1){
    				int x=read(),y=read();
    				swap(a[x],a[y]),pos[a[x]]=x,pos[a[y]]=y;
    				update(1,1,n+1,a[x]),update(1,1,n+1,a[y]);
    			} else printf("%d
    ",Query(1,1,n+1,mp(pos[1],pos[1]))-1);
    		}		
    	}
    }
    int main(){
    	Fuck::Main();
    }
    
  • 相关阅读:
    戴尔服务器IDRAC命令配置IP地址
    python 生成excel,并下载到本地
    python api
    python发送邮件
    大型线上系统迁移为分布式系统案例
    2014程序员之路
    Java EnumSet工作原理初窥
    C# 引用访问权限
    分享一些我的入门经历
    分享一些我的阅读习惯
  • 原文地址:https://www.cnblogs.com/zykykyk/p/10165282.html
Copyright © 2011-2022 走看看