codeforces教育场85 D-Minimum Euler Cycle模拟

在这里插入图片描述
题意:给出一个n个顶点的有向完全图,找出字典序最小的欧拉回路经过的顶点,然后从L输出到R为止。
题解:很容易找到规律,欧拉回路字典序最小的顶点有:
前n*(n-1)项为:1213…1n2324…2n3435…3n,
第n*(n-1)+1项为:1。
很容易看出规律,第一个块有n-1个元素,第二个块有n-2个元素,块内,两个两个为一个部分,奇数部分是表示当前是第几块,偶数部分表示的是当前块+1+(块内第几个元素-1)/2。
那么只需要按照规律来输出就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<algorithm>
#include<sstream>
#include<bitset>
#define scand(a) scanf("%d",&a)
#define scandd(a,b) scanf("%d%d",&a,&b)
#define scanddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mst(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&-x
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=3e5+5;
const ll mod=998244353;
ll l,r;
ll n;
int main()
{
	#ifdef local
	freopen("1.txt","r",stdin);
	#endif
	int T;
	scand(T);
	while(T--)
	{
		scanf("%lld",&n);
		scanf("%lld%lld",&l,&r);
		ll now=1;
		ll k=l;
		while(now<n&&k>(n-now)*2)//快速找出当前L所处的块以及在块中的位置
		{
			k-=2LL*(n-now);
			now++;
		}
		k--;
		//显然如果当前L为偶数的话,那么会除于2会位于下一位,
		//所以要自减,奇数/2本身向下取整所以自减没影响。
		for(ll i=l;i<=r;i++)
		{
			if(i==1LL*n*(n-1)+1)//如果当前i是最后一位,那么直接输出1就行了
			{
				printf("1");
				break;
			}
			if(i%2)printf("%lld ",now);//显然根据上面的规律,奇数位置永远是表示第几块
			else 
			{
				printf("%lld ",k/2+now+1);//否则就输出是块中的第几个元素
				if(k/2+now+1==n)//如果当前已经是第N个元素了,那么就重头再来就是了
				{
					now++;
					k=0;
					continue;
				}
				k+=2;
			}
		}
		printf("\n");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值