P1963 [NOI2009]变换序列

本文介绍了一种解决NOI2009变换序列问题的方法,通过将问题转化为环上距离的计算,并利用二分图上的匈牙利算法求解完美匹配。详细解析了代码实现过程,包括节点位置选择、边的连接和匹配检查。

题目描述

不想水字,详见某谷:P1963 [NOI2009]变换序列

 

solution

其实  D(x,y)  的计算就类似于环上的距离。

对于每一个 i 都可能有两种位置选择:(i+d[i])\,\,\,\,mod\, \,\,\,n(i-d[i]+n)\,\,\,\,mod\,\,\,\,n 。

所以把它们分别连边,二分图上匈牙利算法求完美匹配即可。

#include<iostream>
#include<cstdio>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FR(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int MAXN=20005;
bool vis[MAXN];
int d[MAXN],e[MAXN][2],X[MAXN],Y[MAXN];
inline int read()
{
	int f=1,x=0; char c=getchar();
	while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
	while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
	return x*f;
}
bool check(int u)
{
	for (int i=0;i<=1;i++)
	    if (!vis[e[u][i]])
	    {
	    	int to=e[u][i];
	    	vis[to]=1;
	    	if (X[to]==-1||check(X[to])) { X[to]=u; Y[u]=to; return 1; }
		}
	return 0;
}
int main()
{
	int n=read();
	for (int i=1;i<=n;i++) d[i]=read(); 
	for (int i=1;i<=n;i++)
	{
		e[i][0]=(i+d[i]-1)%n+1,e[i][1]=(i-d[i]+n-1)%n+1;
		if (e[i][0]>e[i][1]) swap(e[i][0],e[i][1]);
		X[i]=Y[i]=-1;
	}
	for (int i=n;i>=1;i--)
	{
		for (int j=1;j<=n;j++) vis[j]=0;
		if (!check(i)) { puts("No Answer"); return 0; }
	}
	for (int i=1;i<=n;i++) printf("%d ",Y[i]-1);
	return 0;
}

 

P5996【NOI2025】序列变换 NOI/NOI+/CTSC NOI 标准IO 传统题 来源 OJ小柴 时间限制 6000ms 内存限制 1023MB-1024MB 通过/尝试次数 58/167 题目背景 NOI 2025 真题 题目描述 给定两个长度为 n 的整数序列 B = [b1, . . . , bn],C = [c1, . . . , cn]。对于长度为 n 的非负整数序列 D = [d1, . . . , dn],设 S(D) 为所有满足 di = 0 的下标 i 的集合,定义f(D) = ∑i∈S(D)bi,g(D) = ∏i∈S(D)ci。特别地,若 S(D) 为空,则 f(D) = 0,g(D) = 1。 小 L 有一个长度为 n 的正. 整. 数. 序. 列. A = [a1, . . . , an]。小 L 可以对序列 A 做如下修改: • 选择序列 A 的两个相. 邻. 的下标 i, j(即 1 ≤ i, j ≤ n 且 |i − j| = 1),若 ai ≤ aj,则将 aj 改为 aj − ai,同时将 ai 改为 0。 小 L 可以进行任意多次修改操作,也可以不进行任何修改。对于所有序列 A 通过以上修改操作可以得到的序列 D,小 L 想求出 f(D) 的最大值以及 g(D) 之和,请你帮助他求出这两个值。形式化地,记 T(A) 为序列 A 通过以上修改操作可以得到的所. 有. 序.列 .的 .集 .合,你需要求出 maxD∈T(A) f(D) 以及 ∑D∈T(A)g(D)。其中,由于 ∑D∈T(A)g(D)可能较大,你只需要求出其对 1, 000, 000, 007 取模后的结果 输入格式 从文件 sequence.in 中读入数据。 本题包含多组测试数据。 输入的第一行包含两个非负整数 c, t,分别表示测试点编号与测试数据组数。c = 0 表示该测试点为样例。 接下来依次输入每组测试数据,对于每组测试数据: 第一行包含一个正整数 n,表示序列长度。 第二行包含 n 个正整数 a1, . . . , an,表示序列 A。 第三行包含 n 个整数 b1, . . . , bn,表示序列 B。 第四行包含 n 个正整数 c1, . . . , cn,表示序列 C。 输出格式 输出到文件 sequence.out 中。 对于每组测试数据,仅输出一行,其中包含两个整数,分别表示 maxD∈T(A) f(D)以及 ∑D∈T(A)g(D) 对 1, 000, 000, 007 取模后的结果。 注意:maxD∈T(A) f(D) 不需要对1, 000, 000, 007 取模。 本题包含两个小问,正确回答其中任意一个小问均可获得部分分数。 输入 #1 input1 复制 0 3 3 5 6 6 3 6 9 1 2 3 6 1 1 4 5 1 4 ‐1 1 ‐1 1 ‐2 2 1 1 1 1 1 1 8 4 2 4 2 2 2 4 4 ‐2 4 9 ‐3 4 8 7 8 1 1 1 1 1 1 1 1 输出 #1 output1 复制 15 10 1 18 37 48 提示 【样例解释】 该样例共包含三组测试数据。 对于第一组测试数据,可以得到以下 4 个序列: • D = [5, 6, 6],f(D) = 0,g(D) = 1; • D = [0, 1, 6],f(D) = 3,g(D) = 1; • D = [5, 0, 0],f(D) = 6 + 9 = 15,g(D) = 2 × 3 = 6; • D = [0, 0, 5],f(D) = 3 + 6 = 9,g(D) = 1 × 2 = 2。 故 maxD∈T(A) f(D) = max{0, 3, 15, 9} = 15,∑D∈T(A)g(D) = 1 + 1 + 6 + 2 = 10。 【数据范围】 设 N 为单个测试点内所有测试数据的 n 的和。对于所有测试数据,保证: • 1 ≤ t ≤ 20; • 1 ≤ n ≤ 5, 000,N ≤ 4 × 104; • 对于所有 1 ≤ i ≤ n,均有 1 ≤ Ai ≤ 109; • 对于所有 1 ≤ i ≤ n,均有 −109 ≤ Bi ≤ 109; • 对于所有 1 ≤ i ≤ n,均有 1 ≤ Ci ≤ 109 特殊性质 A:保证 A1 = A2 = · · · = An = 1。 特殊性质 B:保证对于所有 1 ≤ i ≤ n,Ai 均在 [1, 109] 中独立均匀随机生成。c++
最新发布
09-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值