CF320B解题报告
题意
有一些区间,当且仅当一个区间包含另一个区间的起点或终点时,这两个区间可以互相到达。
需要处理两种操作:
- 添加一个区间,保证这个区间的长度严格大于之前区间的长度。
- 询问一个区间是否能到达另一个区间。
分析
不难看出可以建图然后 dfs 一遍看起点能不能到达终点。
对于添加操作,相当于建图,如果区间 \(x\) 能到达区间 \(y\)(满足题面上的条件),那么就连一条边,建反边同理(可以从 \(y\) 转移到 \(x\))。
对于查询操作,直接 dfs 看能不能从 \(a\) 区间到达 \(b\) 区间,dfs 部分不再赘述,最后输出。
代码
#include <bits/stdc++.h>
using namespace std;
int n, len, flag;
int l[105], r[105], vis[105];
vector<int> g[105];
void dfs(int x, int ex){
if (flag) return ;
if (x == ex){//走到了
flag = 1;
return ;
}
vis[x] = 1;
for (int i = 0; i < g[x].size(); i++){
int v = g[x][i];
if (vis[v] == 0) dfs(v, ex);
}
}
int main(){
cin >> n;
for (int i = 1, opt, x, y; i <= n; i++){
cin >> opt >> x >> y;
if (opt == 1){
l[++len] = x, r[len] = y;
for (int i = 1; i < len; i++){//这里只需要遍历已经添加过的边,后面加进来的边也会再来一次,建反边时相当于从这里建了一条正边
if ((l[i] < l[len] && l[len] < r[i]) || (l[i] < r[len] && r[len] < r[i])) g[len].push_back(i);//满足条件建边
if ((l[len] < l[i] && l[i] < r[len]) || (l[len] < r[i] && r[i] < r[len])) g[i].push_back(len);//建反向边
}
}
else{
memset(vis, 0, sizeof(vis));//记录每个点是否走过
flag = 0;
dfs(x, y);//看能不能从x移动到y
if (flag == 1) cout << "YES\n";
else cout << "NO\n";
}
}
return 0;
}