题意理解(建议先自己把原题描述看一遍再来看我的理解)
有一个集合,这个集合的元素是区间,一开始集合里只有一个元素就是 \([1,n]\) 的区间,对这个集合我们可以选择其中的一个元素(区间),然后在区间内选一个数d,以 \([l,d-1]\) 和 \([d+1,r]\) 这两个区间替换掉我们选择的这个区间( \(l\) 和 \(r\) 分别是我们从集合里面选择出来的这个元素的左端点和右端点)。当然这两个新区间必须存在才行,左端点小于等于右端点。如果不存在就不加入到集合中。我们选择\(n\)个数后,集合内元素个数为 \(0\),也就是区间个数为 \(0\) 时结束。
现在题目给出的是每次操作时选择的那个区间,要你推出对应的d。比如现在有一个集合 \(S\),里面有一个元素,区间\([1,6]\)。
第一次操作,选[1,6],d取2,对S,删去[1,6],加入[1,1]和[3,6],现S={[1,1],[3,6]}。
第二次操作,选[1,1]进行操作,d取1,对S,删去[1,1],现S={[3,6]}。
第三次操作,选[3,6]进行操作,d取6,对S,删去[3,6],加入[3,5],现S={[3,5]}。
第四次操作,选[3,5]进行操作,d取3,对S,删去[3,5],加入[4,5],现S={[4,5]}。
第五次操作,选[4,5]进行操作,d取5,对S,删去[4,5],加入[4,4],现S={[4,4]}。
第六次操作,选[4,4]进行操作,d取4,对S,删去[4,4],现S为空,游戏结束。
现题目打乱顺序的给出 $[1,6],[1,1],[3,6],[3,5],[4,5],[4,4] $这六个区间,要求你推出每个区间对应的d,并输出,可以不按照题目的顺序。
题解
看似很复杂的一道题,我们可以从简单的角度入手,对于左右端点相等的区间,\(d\) 只能选择端点值,所以我们先确定所有左右端点相等区间对应的 \(d\) 值。其实我们可以简单的理解为每次操作删掉 \([1,n]\) 之间的一个数,所以删过的数就不可能再次出现,也就是每个区间对应的\(d\)值都不相同。所以我们标记掉出现过的 \(d\)。于是我们有了这样一个思路,随着迭代的进行被标记的 \(d\) 越来越多,对于区间越来越大,但是找到 \(d\) 的难度相当,因为区间越大时被标记的 \(d\) 就越多。我们将区间以从小到大的顺序排列,对于长度为 \(1\) 的区间直接找到 \(d\) 值,对于长度为 \(2\) 的区间只有两个可能的 \(d\) 值,但此前我们标记了一个 \(d\) 值,所以对于长度为 \(2\) 的区间也只有一个确定的 \(d\) 值,以此类推。所有的区间我们都能找到一个 \(d\) 值与之对应。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LM LLONG_MAX
#define IM INT_MAX
#define N 1001
struct pair1{
int l;
int r;
int len;
int d=0;
};
bool cmp(pair1 a,pair1 b){
return a.len<b.len;
}
int main(){
int t;
cin>>t;
while(t--){
bool vis1[N]={0};
int n,ans[N];
cin>>n;
pair1 a[N];
for(int i=1;i<=n;i++){
cin>>a[i].l>>a[i].r;
a[i].len=a[i].r-a[i].l;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
if(a[i].l==a[i].r){
a[i].d=a[i].l;
vis1[a[i].d]=true;
}
else {
for(int j=a[i].l;j<=a[i].r;j++){
if(!vis1[j]){
a[i].d=j;
vis1[j]=true;
}
}
}
}
for(int i=1;i<=n;i++) cout<<a[i].l<<" "<<a[i].r<<" "<<a[i].d<<endl;
}
}
标签:CF1623B,题解,int,Game,端点,删去,区间,操作,集合
From: https://www.cnblogs.com/deviance/p/18102628