梦熊十三连测第二场题解

T1

手动模拟一下过程可以发现:

ai2,ai,ai+2 总是相邻的,且 a1,a2 是相邻的,an 在最左端。

  • n 为奇数,答案为 anan2...a1+a2a4...an1。​
  • n 为偶数,答案为anan2...a2+a1a3...an1​。

时间复杂度 O(n)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int n;
int a[N];
int b[N];
signed main(){
	freopen("reverse.in","r",stdin);
	freopen("reverse.ans","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	int cnt=0;
	for(int i=n,j=1;i>(n%2==1?-1:0);i-=2,j++){
		b[j]=a[i];
		if(i!=1)b[n-j+1]=a[i-1];
	}
	for(int i=1;i<=n;i++)cout<<b[i]<<" ";
	return 0;
}

T2

如果一条边不在图中一棵最小生成树中,那么加入一条新边之后的新图中也可以不用考虑这条边了。(考虑kruskal将边排序的过程)

对原图使用 prim 求出最小生成树的 n1 条边,与新加入的 q 条边排序后,做 q​ 次 kruskal 即可。

时间复杂度 O(n2+nqlogn)。(logn 为并查集)

T3

ai<aj,bi>bj

[(aibi)2+(ajbj)2][(aibj)2+(ajbi)2]=2(bjbi)(aiaj)>0

那么交换 ai,aj 使总距离减小,设 a 为最优序列。

则对于 i=1...n,若 bib 中第 k 大数,那么 ai 也为 a 中第 k 大数。

a 中位置 i 上的数的最终的位置为 pi,交换操作相当于交换 pi,pj。最后需要让 pi=i

ipi 连边,会形成若干个环,每次交换会让环数加一或者减一,最小交换次数即为 n

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+10,mod=998244353;
int n,T;
struct node{
	int pos,val;
}a[N],b[N];
bool cmp(node x,node y){
	return x.val<y.val;
}
int ans;
int sum;
int id;
int vis[N];
int dfncnt;
int dfn[N],fa[N];
int stc[N];
int tp;
vector < int > edge[N],ring[N];
void dfs(int x){
	dfn[x]=++dfncnt;
	for(auto v :edge[x]){
		if(v==fa[x])continue;
		if(!dfn[v]){
			fa[v]=x;
			dfs(v);
		}
		else if(dfn[v] > dfn[x]){
			int tmp=v;
			id++;
			while(tmp!=fa[x]){
				vis[tmp]=1;
				ring[id].push_back(tmp);
				tmp=fa[tmp];
			}
		}
	}
}
signed main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.ans","w",stdout);
	cin>>n>>T;
	for(int i=1;i<=n;i++)a[i].pos=i,b[i].pos=i;
	for(int i=1;i<=n;i++)cin>>a[i].val;
	for(int i=1;i<=n;i++)cin>>b[i].val;
	sort(a+1,a+1+n,cmp);
	sort(b+1,b+1+n,cmp);
	for(int i=1;i<=n;i++){
		edge[a[i].pos].push_back(b[i].pos);
		edge[b[i].pos].push_back(a[i].pos);
		sum+=(((a[i].val-b[i].val)%mod)*((a[i].val-b[i].val)%mod))%mod;
	}
	sum%=mod;
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			dfs(i);
		}
	}
	for(int i=1;i<=id;i++){
		ans+=ring[i].size()-1;
	}
	cout<<sum;
	if(T==1)cout<<' '<<ans<<'\n';
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}

T4

枚举方阵的大小为 k,每行给定一个权值 xi,每列给定一个权值 yi,那么 ai,j=xi+yj​ 是一个合法的方阵。

一个合法的方阵也一定可以由一组 xi,yi 表示。(xi=ai,1,yj=a1,ja1,1)

但是xi=xi+1,yi=yi1xi,yi 对应的方阵相同。

min(xi)=0 则方阵与数列之间一一对应。

此时 ai,jm等价于 min(yi)m

yi 减去 m,问题变为将至多 nkm个石头放入2k个格子里,且前k个格子至少有一个没有石子的方案数。

容斥求得答案为(nkm+2k2k)(nkm+k2k)

最后对所有可能的k 求和。

posted @   ?x?  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示