# C - Connections

thinking

Give you a picture that can reach any point, m > 2 ∗ n , m < 100000 m>2*n, m<100000 m> 2 * n, m < 100000, delete m − 2 ∗ n m-2*n m − 2 * n paths make this map still reach any point

I thought about finding a ring in this picture. Later, I found that there will be many rings. Title left 2 ∗ n 2*n 2 * n is to find 1 1 1 to other points and other points to 1 1 It's impossible to find the way to one at other points, so it's just to run through the forward graph and the reverse graph 1 1 1 start

```#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+6;
vector<pair<int, int> > g[N], fan[N];
pair<int, int> a[N];
bool vis[N], vis1[N];
void dfs(int u) {
vis[u]=1;
for(auto v:g[u]) {
int x=v.first;
if(!vis[x]) {
vis1[v.second]=1;
dfs(x);
}
}
}
void dfs1(int u) {
vis[u]=1;
for(auto v:fan[u]) {
int x=v.first;
if(!vis[x]) {
vis1[v.second]=1;
dfs1(x);
}
}
}
signed main() {
int t; cin>>t;
while(t--) {
int n, m; cin>>n>>m;
for(int i=1; i<=n; i++) g[i].clear(), fan[i].clear();
for(int i=1; i<=m; i++) {
int x , y; cin>>x>>y;
g[x].push_back(make_pair(y, i));
fan[y].push_back(make_pair(x, i));			//Build reverse edge
a[i]=make_pair(x, y);
vis1[i]=0;
}
for(int i=1; i<=n; i++) vis[i]=0;
dfs(1);
for(int i=1; i<=n; i++) vis[i]=0;
dfs1(1);
int cnt=m-2*n;
for(int i=1; i<=m; i++)
if(!vis1[i]) {
cnt--;
cout<<a[i].first<<" "<<a[i].second<<endl;
if(cnt==0) break;
}
}
return 0;
}
```

# D - Designing the Toy

thinking
Give you the area of three views a b c abc abc
Let you use 1 ∗ 1 ∗ 1 1 * 1 * 1 The cube structure of 1 * 1 * 1 satisfies a b c abc abc

repair
First put an abc du-1 in 000
If a < b ∗ c a<b*c A < b * c put 001 002 003
until a > b ∗ c a>b*c a> B * c can be placed on one side
Reclassification discussion a a a and b c b c bc situation

```#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N=1e5+5;
int a[5];
struct node {
int x, y, z;
};
vector<node> ans;
int main() {
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int a, b, c;
cin>>a>>b>>c;
if(a>b*c||b>c*a||c>a*b) {
cout<<-1<<endl;
return 0;
}
ans.push_back({0,0,0});
a--,b--,c--;
int cnt=0;
while(a<b*c) {
b--, c--;
ans.push_back({0,0,++cnt});
}
if(a>=b+c) {		// You can cover both sides. a is enough
for(int i=1; i<=b; i++)  ans.push_back({i,0,0}), a--;
for(int i=1; i<=c; i++)  ans.push_back({0,i,0}), a--;
if(a) {			// It is possible that a > b + C is spread on both sides and then placed in the middle
for(int i=1; i<=b; i++) {
for(int j=1; j<=c; j++) {
ans.push_back({i,j,0});
a--;
if(!a) break;
}
if(!a) break;
}
}		// A = = b * C and a < B + C, there are only two possible cases
}else if(a==b*c) {  		// Case 1: one is 1. Move up one
if(c==1)for(int i=1; i<=b; i++) ans.push_back({i,1,0});
else if(b==1)for(int i=1; i<=c; i++) ans.push_back({1,i,0});
}else{			//Case 2: one is 0
if(!b) {
for(int i=1; i<=a; i++) ans.push_back({0,i,0}), c--;
if(c) {
for(int i=1; i<=a; i++) {
for(int j=1; j<=cnt; j++) {			// cnt is the height of the z axis
ans.push_back({0,i, j});
c--;
if(!c) break;
}
if(!c) break;
}
}
}else if(!c) {			//2
for(int i=1; i<=a; i++) ans.push_back({i,0,0}), b--;
if(b) {
for(int i=1; i<=a; i++) {
for(int j=1; j<=cnt; j++) {
ans.push_back({i,0, j});
b--;
if(!b) break;
}
if(!b) break;
}
}
}
}
cout<<ans.size()<<endl;
for(auto v:ans) {
cout<<v.x<<" "<<v.y<<" "<<v.z<<endl;
}
return 0;
}
```

# A - Archery Tournament

Mess or segment tree + set
Question meaning: give n operations,
Operation 1 means to establish a target at (x,y) with radius y.
Operation 2 means firing a shot at (x,y).
It is required to give whether the gun hits the target or not every time the gun is fired. If it does, the target number will be output, and the target will be deleted. If it does not hit, the output will be - 1

repair
Using set to save the left and right boundaries, and then bisecting directly to find the two sides doesn't seem very good
Then change your mind and find the circle after (current x-maximum radius) check
But it will be t, so just find the center of the circle x x X is less than (current x + maximum radius)
Line segment tree method

```#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=200005;
struct node {
int x, y, id;
bool operator<(const node &rhs)const{
return x<rhs.x;
}
};
set<node> se;
signed main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n; cin>>n;
int mr=0;
for(int i=1; i<=n; i++) {
int x, y, op; cin>>op>>x>>y;
if(op==1) {
se.insert({x, y, i});
mr=max(mr, y);
}else {
set<node>::iterator it = se.lower_bound({x-mr, y, 0});		//If x is greater than or equal to x, it will leak
bool flag=0;
while(it!=se.end()) {
node pp=(*it);
if(pp.x>x+mr) break;		//break without
if((pp.x-x)*(pp.x-x)+(pp.y-y)*(pp.y-y)<pp.y*pp.y) {
cout<<pp.id<<endl;
se.erase(it);
flag=1;
break;
}
it++;
}
if(!flag) cout<<-1<<endl;
}
}
return 0;
}
```

# L. Laminar Family

Tree chain subdivision + LCA + line segment tree
Give a tree and a set of operations. The format of the operation is given u v uv uv two nodes, and add all the nodes on the path determined by the node to a new set.
If any two of all sets meet the requirements, either contain each other or do not intersect, then Yes is output, otherwise No is output

Not supplemented
Stick the guy's code

```#include<bits/stdc++.h>
#define all(x) x.begin(), x.end()
template <typename T>
void read(T & x){ x = 0;T f = 1;char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;
ch = getchar();}while (isdigit(ch)){x = x * 10 + (ch ^ 48);ch = getchar();}x *= f;}

using namespace std;
const int N = 100010, M = N << 1;

int n, m, idx, ne[M], e[M], h[N];
int sz[N], dep[N], fa[N], son[N], f[N][20], id[N], tot, top[N];
struct node{
int l, r, col, lz;
}tr[N << 2];
struct Q{
int l, r, dep, id;
bool operator < (const Q& rhs) const{
return dep > rhs.dep;
}
};  vector<Q> Qu;
void GG(){ cout << "No"; exit(0); }
void add(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx ++;}
void pushup(int u){tr[u].col = (tr[u << 1].col == tr[u << 1 | 1].col ? tr[u << 1].col : -1);}
void pushdown(int u){
node& rt = tr[u], &le = tr[u << 1], &ri = tr[u << 1 | 1];
if(!rt.lz)  return ;
le.lz = ri.lz = le.col = ri.col = rt.lz;
rt.lz = 0;
}
void build(int u, int l, int r){
tr[u] = {l, r, 0, 0};
if(l == r)  return ;
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}
int modify(int u, int l, int r, int new_col){
if(tr[u].l >= l and tr[u].r <= r){
if(tr[u].col == -1) GG();
int res = tr[u].col;
tr[u].col = new_col, tr[u].lz = new_col;
return res;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1, ri = -2, le = -2;
if(l <= mid)    le = modify(u << 1, l, r, new_col);
if(r > mid)     ri = modify(u << 1 | 1, l, r, new_col);
if(ri != -2 and le != -2 and ri != le)  GG();
pushup(u);
return max(le, ri);
}
void dfs1(int u, int father){
sz[u] = 1, dep[u] = dep[father] + 1, fa[u] = father;
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if(j == father) continue ;
f[j][0] = u;
for(int k = 1; k <= 19; ++ k)   f[j][k] = f[f[j][k - 1]][k - 1];
dfs1(j, u);
sz[u] += sz[j];
if(sz[son[u]] < sz[j])  son[u] = j;
}
}
void dfs2(int u, int t){
id[u] = ++ tot, top[u] = t;
if(!son[u]) return ;
dfs2(son[u], t);
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if(j == fa[u] or j == son[u])   continue ;
dfs2(j, j);
}
}
int lca(int a, int b){
if(dep[a] < dep[b]) swap(a, b);
for(int i = 19; i >= 0; -- i)   if(dep[f[a][i]] >= dep[b])    a = f[a][i];
if(a == b)  return a;
for(int i = 19; i >= 0; -- i)   if(f[a][i] != f[b][i])  a = f[a][i], b = f[b][i];
return f[a][0];
}
void query_path(int u, int v, int new_col){
int res = -2;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]])   swap(u, v);
int now = modify(1, id[top[u]], id[u], new_col);
if(res == -2)   res = now;
else if(res != now) GG();
u = fa[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
int now = modify(1, id[v], id[u], new_col);
if(res == -2)   res = now;
else if(res != now) GG();
}
signed main(){
memset(h, -1, sizeof h);
for(int i = 1, a, b; i <= n - 1; ++ i){
}
memset(dep, 0x3f, sizeof dep); dep[0] = 0;
dfs1(1, 0);
dfs2(1, 1);
build(1, 1, n);
for(int i = 1; i <= m; ++ i){
int l, r;