Codeforces1334D. Minimum Euler Cycle(贪心\模拟)

Description

You are given a complete directed graph Kn with n vertices: each pair of vertices u≠v in Kn have both directed edges (u,v) and (v,u); there are no self-loops.

You should find such a cycle in Kn that visits every directed edge exactly once (allowing for revisiting vertices).

We can write such cycle as a list of n(n−1)+1 vertices v1,v2,v3,…,vn(n−1)−1,vn(n−1),vn(n−1)+1=v1 — a visiting order, where each (vi,vi+1) occurs exactly once.

Find the lexicographically smallest such cycle. It’s not hard to prove that the cycle always exists.

Since the answer can be too large print its [l,r] segment, in other words, vl,vl+1,…,vr.

Input

The first line contains the single integer T (1≤T≤100) — the number of test cases.

Next T lines contain test cases — one per line. The first and only line of each test case contains three integers n, l and r (2≤n≤105, 1≤l≤r≤n(n−1)+1, r−l+1≤105) — the number of vertices in Kn, and segment of the cycle to print.

It’s guaranteed that the total sum of n doesn’t exceed 105 and the total sum of r−l+1 doesn’t exceed 105.

Output

For each test case print the segment vl,vl+1,…,vr of the lexicographically smallest cycle that visits every edge exactly once.

题目大意

有n个点,每两个点之间都有两条单向的联通路径,求一个长度为2*n的回路,每条路径只能走一次,需要走过的点字典序最小
输出走过的点中区间为l~r的点

贪心构造一下就可以发现路径为

1 2 3 1 4 1 5...1 n   2 3 2 4 2 5...2 n   3 4 3 5... 3 n  ...   n-1 n 1

然后就是模拟输出

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+5;
const int inf=0x3f3f3f3f;
ll ans[maxn];
int main()
{
    int t;
    ll n,l,r,num,m,mm;
    scanf("%d",&t);
    while(t--){
        scanf("%lld %lld %lld",&n,&l,&r);
        m=n-1,mm=1,num=1;
        while(num+2*m<=l&&m){
            num+=2*m;
            --m,++mm;
        }
        int cnt=0;
        while(num<=r&&m){
            for(int i=(n-m+1);i<=n;++i){
                if(num>=l&&num<=r)ans[++cnt]=mm;
                ++num;
                if(num>=l&&num<=r)ans[++cnt]=i;
                ++num;
            }
            --m;
            ++mm;
        }
        if(num==r)ans[++cnt]=1;
        for(int i=1;i<cnt;++i){
            printf("%d ",ans[i]);
        }
        printf("%d\n",ans[cnt]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43984169/article/details/106059764