Educational Codeforces Round 85 D. Minimum Euler Cycle(模拟/数学/图)
You are given a complete directed graph KnKn with nn vertices: each pair of vertices u≠vu≠v in KnKn have both directed edges (u,v)(u,v) and (v,u)(v,u) ; there are no self-loops.
You should find such a cycle in KnKn that visits every directed edge exactly once (allowing for revisiting vertices).
We can write such cycle as a list of n(n−1)+1n(n−1)+1 vertices v1,v2,v3,…,vn(n−1)−1,vn(n−1),vn(n−1)+1=v1v1,v2,v3,…,vn(n−1)−1,vn(n−1),vn(n−1)+1=v1 — a visiting order, where each (vi,vi+1)(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][l,r] segment, in other words, vl,vl+1,…,vrvl,vl+1,…,vr .
The first line contains the single integer TT (1≤T≤1001≤T≤100 ) — the number of test cases.
Next TT lines contain test cases — one per line. The first and only line of each test case contains three integers nn , ll and rr (2≤n≤1052≤n≤105 , 1≤l≤r≤n(n−1)+11≤l≤r≤n(n−1)+1 , r−l+1≤105r−l+1≤105 ) — the number of vertices in KnKn , and segment of the cycle to print.
It's guaranteed that the total sum of nn doesn't exceed 105105 and the total sum of r−l+1r−l+1 doesn't exceed 105105 .
For each test case print the segment vl,vl+1,…,vrvl,vl+1,…,vr of the lexicographically smallest cycle that visits every edge exactly once.
3 2 1 3 3 3 6 99995 9998900031 9998900031
1 2 1 1 3 2 3 1
整个走法应该是1 2 1 3 1 4 1 5 ...1 n 2 3 2 4 2 5..2 n ... n-1 n 1,划分一下就是[1 2 1 3 1 4 1 5] [2 3 2 4 2 5] [3 4 3 5] [4 5] [1]这样,不难发现规律。因为要满足字典序最小,所以先从1到2 3 4 5,这时如果直接回去的话必然重复,所以只能从5走到2....这样下去。
所以判断一下l和r所处情况,输出即可。注意特判最后一个区间,以及开long long
(代码垃圾,不要参考
#include <bits/stdc++.h> using namespace std; long long n,l,r; long long get(long long p) { long long ans=0; long long i; for(i=0;i<=n-1;i++) { if(p>i*(2*n-1-i)&&p<=(i+1)*(2*n-2-i))ans=i+1; if(ans)break; } if(p==n*(n-1)+1)ans=n-1; return ans; } int main() { int t; cin>>t; while(t--) { scanf("%lld%lld%lld",&n,&l,&r); if(l==r&&l==(n-1)*n+1) { cout<<'1'<<endl; continue; } long long ls=get(l),rs=get(r),i,j;//ls是l所处的区间的标志 2 3 2 4 2 5 2 6标志为2 long long a=l-(ls-1)*(2*n-ls),//a是l在那一组的位置 b=(r==(n-1)*n+1)? 2*(n-rs):r-(rs-1)*(2*n-rs);//处理一下,因为r可能是最后 if(ls==rs)//特判 { if(l%2==0) { cout<<a/2+ls<<' '; for(j=a/2+ls+1;j<=b/2+rs;j++)cout<<ls<<' '<<j<<' '; } else { for(j=(a+1)/2+ls;j<=b/2+rs;j++) printf("%lld %lld ",ls,j); } if(b%2!=0)cout<<rs<<' '; if(r==n*(n-1)+1)cout<<1; cout<<endl; continue; } if(a%2==0)//左半截 { cout<<a/2+ls<<' '; for(j=a/2+ls+1;j<=n;j++) printf("%lld %lld ",ls,j); } else { for(j=(a+1)/2+ls;j<=n;j++) printf("%lld %lld ",ls,j); } for(i=ls+1;i<=rs-1;i++)//中间 { for(j=i+1;j<=n;j++) { printf("%lld %lld ",i,j); } } //右半截 { for(i=1;i<=b/2;i++) { printf("%lld %lld ",rs,i+rs); } if(b%2!=0)cout<<rs; } if(r==n*(n-1)+1)cout<<1;//特判 cout<<endl; } return 0; }