其他分享
首页 > 其他分享> > LGP6305题解

LGP6305题解

作者:互联网

笑死,细节问题直接把自己送走了,100pts->0pts。

个人认为是模拟赛最简单的一道题 可能是因为我倒开

如果 \(a\) 中元素互不相同很好做,排序然后变成 \(i\) 应该去到 \(p_i\) 的位置,直接连接 \((i,p_i)\) 然后输出每个环即可。

但是可能出现不相同的元素。

考虑对于排序后的序列,一段区间 \([L,R]\) 满足权值相等,并记 \(q[i]\) 为 \(p\) 的逆置换。(也就是谁要到这里来)

然后会发现,这些 \(q\) 有可能互相不属于相同的环,但是显然可以通过令 \(q[i]\) 连接 \(i+1\)(\(i=R\) 特判)来做到变为一个环。

然后还需要注意的是,实际上可以花费 \(s\) 的代价,将 \(s\) 个环拼接在一起,然后再加一次操作。

具体来讲就是像上面一样把环混在一起,然后交换哪些不正确的位置,样例 \(4\) 有体现这个。

剩下的就是细节了,复杂度 \(O(n\log n)\),排序和并查集即可。

#include<algorithm>
#include<cstdio>
#include<cctype>
#include<vector>
namespace SOLVE{
	const int M=2e5+5;
	int n,m,s,len,f[M],a[M],b[M],p[M],t[M],id[M];bool vis[M];std::vector<int>q[M];
	inline int read(){
		int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
	}
	inline void write(int n){
		static char s[15];int top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top]),--top);
	}
	inline int Find(const int&u){
		return f[u]==u?u:f[u]=Find(f[u]);
	}
	inline void main(){
		n=read();s=read();for(int i=1;i<=n;++i)b[i]=a[i]=read();std::sort(b+1,b+n+1);
		for(int i=1;i<=n;++i)if(a[i]!=b[i])id[++len]=i,t[len]=i;if(len>s)return printf("-1"),void();
		std::sort(id+1,id+len+1,[&](const int&x,const int&y){return a[x]==a[y]?x<y:a[x]<a[y];});
		for(int i=1;i<=len;++i)p[id[i]]=t[i];s-=len;
		for(int i=1;i<=n;++i)if(!f[i]&&a[i]!=b[i]){
			int j=i;do f[j]=i;while((j=p[j])^i);
		}
		for(int R,L=1;L<=len;L=R+1){
			for(R=L;R<len&&a[id[R+1]]==a[id[L]];++R);vis[Find(id[L])]=true;
			static int m,x[M],y[M];m=1;x[m]=id[L];y[m]=t[L];
			for(int i=L+1;i<=R;++i)if(!vis[Find(id[i])])++m,x[m]=id[i],y[m]=t[i],vis[Find(id[i])]=true;
			if(m^1)for(int i=1;i<=m;++i)p[x[i]]=y[i==m?1:i+1];for(int i=2;i<=m;++i)f[Find(x[i])]=Find(id[L]);
			vis[Find(id[L])]=false;
		}
		int cnt(0);for(int i=1;i<=n;++i)vis[i]=false;
		for(int i=1;i<=n;++i)if(a[i]!=b[i]&&!vis[i]){
			int j=i,cnt(0);do++cnt,vis[j]=true;while((j=p[j])^i);++m;
			j=i;do q[m].push_back(j);while((j=p[j])^i);
		}
		if(s>m)s=m;
		if(!m)write(0);
		else if(m==1){
			write(1);putchar(10);write(q[1].size());putchar(10);for(int&w:q[1])write(w),putchar(32);
		}
		else if(s<=1){
			write(m);putchar(10);
			for(int i=1;i<=m;++i){
				write(q[i].size());putchar(10);for(int&w:q[i])write(w),putchar(32);putchar(10);
			}
		}
		else{
			int sum(0);
			for(int i=1;i<=s;++i)sum+=q[i].size();write(m-s+2);putchar(10);
			write(sum);putchar(10);for(int i=1;i<=s;++i)for(int&w:q[i])write(w),putchar(32);putchar(10);
			write(s);putchar(10);for(int i=s;i>=1;--i)write(*q[i].begin()),putchar(32);putchar(10);
			for(int i=s+1;i<=m;++i){
				write(q[i].size());putchar(10);for(int&w:q[i])write(w),putchar(32);putchar(10);
			}
		}
	}
}
signed main(){
	SOLVE::main();
}

标签:10,putchar,LGP6305,int,题解,write,const,include
来源: https://www.cnblogs.com/lmpp/p/16686480.html