把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

2019.7.17 义乌模拟赛 T2 白兔的旅行

图不连通差评。
可以发现这样建边每个连通块只有一个环。
这样的话环上的点可以任意选择。
但是然后如果你正着这样做不是很好做,考虑反过来。求最长上升就好做了,用一个支持撤销的树状数组维护即可。
时间复杂度\(O(nlogn)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 500000
#define M 50000
#define mod 1000000000
#define mod2 39989
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int A[N+5],n,fa[N+5],un,wn,To[N+5],x,ans,fl[N+5],now,pus,in[N+5],nows[N+5],tots[N+5],B[N+5],Bh,dp[N+5],C[N+5],Ch,FF[N+5];
struct yyy{int to,z;};
struct ljb{
	int head,h[N+5];yyy f[N+5<<1];
	I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}
}s;
I int Getfa(int x){return x==fa[x]?x:fa[x]=Getfa(fa[x]);}
I void ls(int &x){int l=0,r=n+1,mid;while(l+1<r) mid=l+r>>1,(nows[mid]<x?l:r)=mid;x=tots[r];}
struct BIT{
	int F[N+5],st[N+5<<3],sh,W[N+5<<3];
	I void get(int x,int y){while(x<=n) F[x]<y&&(st[++sh]=x,W[sh]=F[x],F[x]=y),x+=x&-x;}
	I int find(int x){int ans=0;while(x) ans=max(ans,F[x]),x-=x&-x;return ans;}
	I void clear(){F[st[sh]]=W[sh];sh--;}
}S;
I void dfs(int x,int last){
	yyy tmp;int lastS=S.sh,i;dp[x]=S.find(A[x]-1)+1;ans=max(ans,dp[x]);S.get(A[x],dp[x]);for(i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(dfs(tmp.to,x),0);while(S.sh^lastS) S.clear();
}
I void find(int x){
	FF[x]=1;C[++Ch]=x;yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],!FF[tmp.to]&&(find(tmp.to),0);
}
I void Make(int x){
	re int i;while(S.sh)S.clear();now=x;while(To[now]^x)fl[now]=1,now=To[now];fl[now]=1;Ch=Bh=0;find(now);
	for(i=1;i<=Ch;i++) fl[C[i]]&&(B[++Bh]=A[C[i]]);sort(B+1,B+Bh+1);for(i=1;i<=Bh;i++) now=S.find(B[i]-1)+1,ans=max(ans,now),S.get(B[i],now);
	for(i=1;i<=Ch;i++) !fl[C[i]]&&fl[To[C[i]]]&&(dfs(C[i],To[C[i]]),0);
}
int main(){
	freopen("travel.in","r",stdin);freopen("travel.out","w",stdout);
	re int i;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d",&A[i]);for(i=1;i<=n;i++) scanf("%d",&To[i]),fa[i]=i,s.add(To[i],i);
	for(i=1;i<=n;i++) nows[i]=A[i];sort(nows+1,nows+n+1);for(tots[1]=1,i=2;i<=n;i++)tots[i]=tots[i-1]+(nows[i]!=nows[i-1]);for(i=1;i<=n;i++) ls(A[i]);
	for(i=1;i<=n;i++) {un=Getfa(i);wn=Getfa(To[i]);if(un==wn)Make(i);fa[un]=wn;}printf("%d\n",ans);
}
posted @ 2021-07-18 06:30  275307894a  阅读(47)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end