Intervals on the Ring

牛客多校6 - I
题目描述

There is a ring of numbers consisting of 1 to n sequentially. For every number i (1 ≤ i ≤ n − 1), i and i+ 1 are adjacent to each other. Particularly, n and 1 are adjacent. We use [l, r] to describe an interval on the ring. Formally, if l ≤ r, then the interval [l, r] is equivalent to the set {l, l + 1, . . . , r −1, r}. Otherwise, the interval [l, r] is equivalent to {l, l + 1, . . . , n, 1, . . . , r−1, r}.
Yukikaze has m non-intersecting intervals. She wants you to construct a set of intervals such that the intersection of them is the union of the m intervals that Yukikaze has. The intersection of the intervals is the set of integers that the intervals have in common.

Input

The first line of the input contains a single integer T (1 ≤ T ≤1000), denoting the number of test cases.
The first line of each test case contains two integers n (3 ≤ n ≤ 1000) and m (1 ≤ m ≤ n), denoting that the ring consists of numbers from 1 to n. Each of the next m lines contains two integers l, r (1 ≤ l, r ≤ n), denoting an interval Yukikaze has.
It’s guaranteed that the m intervals won’t intersect with each other.

Output

For each test case, if the answer doesn’t exist, output −1 in a line.
Otherwise, output an integer k indicating the number of intervals you construct in a line.
Then output the k intervals in k lines. The number of intervals you used should never be less than one or greater than 2000.
If there are multiple solutions, print any. Don’t print any extra spaces at the end of each line.

题意:
构造k个区间使这些区间的交集为给定区间的并集
题目思路:
先找到最左边的点和最右边的点区间为[L,R]这段区间包含所给区间的并集,然后在这段区间中找间断的区间,假设每次找到的间断的区间[l,r],则用
[L,R]U[l-1,r+1]可在[L,R]中去掉找到的间断区间。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000+100;
int a[maxn];
struct node{
	int x,y;
}b[maxn<<2];
int main(){
	int T;
	cin>>T;
	while(T--){
		memset(a,0,sizeof a);
		int cnt=0;
		int n,m;
		cin>>n>>m;
		for(int i=1; i<=m; i++){
			int l,r;
			cin>>l>>r;
			if(r>=l){
				for(int j=l; j<=r; j++)
					a[j]=j;
			}
			if(l>r){
				for(int j=l; j<=n; j++)
				a[j]=j;
				for(int j=1; j<=r; j++)
				a[j]=j;
			}
		}
//		for(int i=1; i<=n; i++){
//			cout<<a[i]<<" ";
//		}
//		cout<<endl;
		int L,R;
		for(int i=1; i<=n; i++){
			if(a[i]!=0){
				L=i;
				break;
			}
		}
		for(int i=n; i>=1; i--){
			if(a[i]!=0){
				R=i;
				break;
			}
		}
		for(int i=L; i<=R; i++){
			int l,r;
			if(a[i]==0){
				l=i-1;
				for(int j=i+1; j<=R; j++){
					if(a[j]!=0){
						r=j;
						break;
					}
				}
				b[cnt].x=r;
				b[cnt++].y=l;
				i=r;
			}
		}
		if(cnt+1>2000)cout<<-1<<endl;
		else {
			cout<<cnt+1<<endl;
			cout<<L<<" "<<R<<endl;
			for(int i=0; i<cnt; i++){
				cout<<b[i].x<<" "<<b[i].y<<endl;
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值