• CF1083C Max Mex


    LINK:CF1083C Max Mex

    鬼题一道 去年开始写 然后咕了很久很久 现在再写。

    考的知识点倒是挺经典的算法 线段树维护树上直径。

    一棵树 有点权 点权为排列 每次询问求出树上一条链的mex的最大值 或者交换两个点的点权。

    analysis:对于这种没有指定链的问题 我们都需要一个数据结构来动态维护答案 或者就在每次修改完就更新答案 一般采用的都是线段树 而这道题也是如此利用线段树来维护mex的最大值。

    具体维护:我们只关心0 1 2 3 4...这些数值的点是否能串成链 可以想到用线段树来维护数值区间 区间有几个信息 L R表示这个区间的数值能否利用L~R这条链给表示出来 这样我们进行区间与区间之间的合并即可。

    怎么合并:考虑两个区间 四个端点 可以证明其他的在这四个端点中间的那些点是没有必要的 这个可以反证。那么如果可以合成一条链 那么这条链的端点肯定也是由这四个点钟的两个点组成的,C(4,2)=6.所以有6种情况,我们暴力枚举哪两个点 然后如何判断?可以发现那么剩下的两个点一定都会在L,R的链上 我们可以利用LCA来判断 剩下的两个点是否在当前组成的链上,如果在那么说明合并成功了。

    考虑求出答案 线段树里只存放了区间合并的结果 并没有答案我们在线段树上二分即可。

    实际写起来比较ex.

    最后再点一下 怎么判断一个点在一条链上:设当前链为x,y lca=LCA(x,y) 判断点w 充要条件:(LCA(x,w)w||LCA(y,w)w)&&LCA(lca,w)==lca.

    可以自己画一下图感受一下。

    (看了一眼以前代码 pushup 写的非常鬼畜 ST表写挂了 ask写挂了 反正一堆毛病...

    又写了一遍 觉得不是很难写 但是觉得处理还是有点麻烦了。

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<cstdlib>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #include<stack>
    #include<iomanip>
    #define INF 100000000000000000ll
    #define ll long long
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    #define db double
    #define EPS 1e-5
    #define us unsigned
    #define l(p) t[p].l
    #define r(p) t[p].r
    #define zz p<<1
    #define yy p<<1|1
    using namespace std;
    char *fs,*ft,buf[1<<15];
    inline char getc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=200010;
    int n,Q,cnt;
    int a[MAXN],L,R,ans;
    int Log[MAXN<<1],v[MAXN<<1],d[MAXN],fir[MAXN],pos[MAXN];
    int f[MAXN<<1][20],q[2];
    vector<int>g[MAXN];
    struct wy
    {
    	int b[2];
    	int l,r;
    	int sum;
    }t[MAXN<<2];
    inline int cmp(int x,int y){return d[x]<d[y]?x:y;}
    inline void dfs(int x)
    {
    	fir[x]=++cnt;v[cnt]=x;
    	for(us int i=0;i<g[x].size();++i)
    	{
    		int tn=g[x][i];
    		d[tn]=d[x]+1;
    		dfs(tn);
    		v[++cnt]=x;
    	}
    }
    inline int LCA(int x,int y)
    {
    	if(!x||!y)return 0;
    	x=fir[x];y=fir[y];
    	if(x>y)swap(x,y);
    	int w=Log[y-x+1];
    	return cmp(f[x][w],f[y-(1<<w)+1][w]);
    }
    inline void pushup(int p)//C(4,2) = 6
    {
    	for(int i=0;i<=1;++i)
    	{
    		for(int j=0;j<=1;++j)
    		{
    			int lca=LCA(t[zz].b[i],t[yy].b[j]);
    			if(!lca)continue;
    			if((LCA(t[zz].b[i],t[zz].b[i^1])==t[zz].b[i^1]||LCA(t[zz].b[i^1],t[yy].b[j])==t[zz].b[i^1]))
    			{
    				if(LCA(lca,t[zz].b[i^1])==lca&&LCA(lca,t[yy].b[j^1])==lca)
    				{
    					if((LCA(t[zz].b[i],t[yy].b[j^1])==t[yy].b[j^1]||LCA(t[yy].b[j^1],t[yy].b[j])==t[yy].b[j^1]))
    					{
    						t[p].b[0]=t[zz].b[i];t[p].b[1]=t[yy].b[j];
    						return;
    					}
    				}
    			}
    		}
    	}
    	int lca=LCA(t[zz].b[0],t[zz].b[1]);
    	if(lca)
    	{
    		if((LCA(t[zz].b[0],t[yy].b[0])==t[yy].b[0]||LCA(t[zz].b[1],t[yy].b[0])==t[yy].b[0]))
    			if(LCA(lca,t[yy].b[0])==lca&&LCA(lca,t[yy].b[1])==lca)
    				if((LCA(t[zz].b[0],t[yy].b[1])==t[yy].b[1]||LCA(t[zz].b[1],t[yy].b[1])==t[yy].b[1]))
    				{
    					t[p].b[0]=t[zz].b[0];t[p].b[1]=t[zz].b[1];
    					return;
    				}
    	}
    	lca=LCA(t[yy].b[0],t[yy].b[1]);
    	if(lca)
    	{
    		if((LCA(t[yy].b[0],t[zz].b[0])==t[zz].b[0]||LCA(t[yy].b[1],t[zz].b[0])==t[zz].b[0]))
    			if(LCA(lca,t[zz].b[0])==lca&&LCA(lca,t[zz].b[1])==lca)
    				if((LCA(t[yy].b[0],t[zz].b[1])==t[zz].b[1]||LCA(t[yy].b[1],t[zz].b[1])==t[zz].b[1]))
    				{
    					t[p].b[0]=t[yy].b[0];t[p].b[1]=t[yy].b[1];
    					return;
    				}
    	}
    	t[p].b[0]=t[p].b[1]=0;
    }
    inline void build(int p,int l,int r)
    {
    	l(p)=l;r(p)=r;
    	if(l==r)
    	{
    		t[p].b[0]=t[p].b[1]=pos[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(zz,l,mid);
    	build(yy,mid+1,r);
    	pushup(p);
    }
    inline void change(int p,int x)
    {
    	if(l(p)==r(p))
    	{
    		t[p].b[0]=t[p].b[1]=pos[l(p)];
    		return;
    	}
    	int mid=(l(p)+r(p))>>1;
    	if(x<=mid)change(zz,x);
    	else change(yy,x);
    	pushup(p);
    }
    inline int merge(int *a,int *b)
    {
    	if(!a[0]){a[0]=b[0];a[1]=b[1];return 1;}
    	for(int i=0;i<=1;++i)
    	{
    		for(int j=0;j<=1;++j)
    		{
    			int lca=LCA(a[i],b[j]);
    			if(!lca)continue;
    			if((LCA(a[i],a[i^1])==a[i^1]||LCA(a[i^1],b[j])==a[i^1]))
    				if(LCA(lca,a[i^1])==lca&&LCA(lca,b[j^1])==lca)
    					if((LCA(a[i],b[j^1])==b[j^1]||LCA(b[j^1],b[j])==b[j^1]))
    					{
    						a[0]=a[i];a[1]=b[j];
    						return 1;
    					}
    		}
    	}
    	int lca=LCA(a[0],a[1]);
    	if(lca)
    	{
    		if((LCA(a[0],b[0])==b[0]||LCA(a[1],b[0])==b[0]))
    				if(LCA(lca,b[0])==lca&&LCA(lca,b[1])==lca)
    					if((LCA(a[0],b[1])==b[1]||LCA(a[1],b[1])==b[1]))return 1;
    	}
    	lca=LCA(b[0],b[1]);
    	if(lca)
    	{
    		if((LCA(b[0],a[0])==a[0]||LCA(b[1],a[0])==a[0]))
    			if(LCA(lca,a[0])==lca&&LCA(lca,a[1])==lca)
    				if((LCA(b[0],a[1])==a[1]||LCA(b[1],a[1])==a[1])){a[0]=b[0];a[1]=b[1];return 1;}
    	}
    	return 0;
    }
    inline int ask(int p)
    {
    	if(t[p].b[1]&&t[p].b[0])
    	{
    		if(merge(q,t[p].b)){ans=max(ans,r(p));return 1;}
    		if(l(p)!=r(p))if(ask(zz))ask(yy);
    		return 0;
    	}
    	if(ask(zz))ask(yy);
    	return 0;
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	n=read();
    	for(int i=1;i<=n;++i)a[i]=read()+1,pos[a[i]]=i;
    	for(int i=2;i<=n;++i)g[read()].push_back(i);
    	dfs(1);Log[0]=-1;
    	for(int i=1;i<=cnt;++i)
    	{
    		Log[i]=Log[i>>1]+1;
    		f[i][0]=v[i];
    	}
    	for(int j=1;j<=Log[cnt];++j)
    		for(int i=1;i<=cnt-(1<<j)+1;++i)
    			f[i][j]=cmp(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    	build(1,1,n);
    	Q=read();
    	for(int i=1;i<=Q;++i)
    	{
    		int op;
    		int x,y;
    		op=read();
    		if(op==1)
    		{
    			x=read();y=read();
    			swap(a[x],a[y]);
    			pos[a[x]]=x;
    			pos[a[y]]=y;
    			change(1,a[x]);
    			change(1,a[y]);
    		}
    		else 
    		{
    			q[0]=q[1]=ans=0;ask(1);
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    (转帖) oracle是否归档模式及修改模式
    (转帖) Oracle实例恢复(Oracle instance recovery)
    实习第一周总结
    UML类图几种关系的总结
    表格排序
    利用js查找页面中的内链,外链
    事件机制(事件冒泡与事件捕获)
    谈 CSS 模块化
    初学后台框架总结篇二——快速了解CI框架
    初学后台框架总结篇一——学习过程
  • 原文地址:https://www.cnblogs.com/chdy/p/12563182.html
Copyright © 2020-2023  润新知