2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)题解+补题
Posted quinn18
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)题解+补题相关的知识,希望对你有一定的参考价值。
文章目录
C - Connections
题目链接
思维
题意:给你一张能到达任意点的图,
m
>
2
∗
n
,
m
<
100000
m>2*n, m<100000
m>2∗n,m<100000,删掉
m
−
2
∗
n
m-2*n
m−2∗n条路使这张图仍然能到达任意点
本来就考虑这张图找一个环,后来发现会有很多环。题目留下 2 ∗ n 2*n 2∗n条就是找 1 1 1到其他点和其他点到 1 1 1的路,总不可能真的找其他点到一的路,所以就是跑一遍正向的图和反向的图从 1 1 1开始
#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)); //建反向边
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
题目链接
思维
题意:给你三视图的面积
a
b
c
abc
abc
让你用
1
∗
1
∗
1
1 * 1 * 1
1∗1∗1的立方体构造满足
a
b
c
abc
abc
补
先在000放一个 abc都-1
如果
a
<
b
∗
c
a<b*c
a<b∗c 就放001 002 003…
直到
a
>
b
∗
c
a>b*c
a>b∗c就可以在一个面上放了
再分类讨论
a
a
a和
b
c
b c
bc的情况
图是a>=b+c的情况
#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) // 可以把两边都铺满, a是足够的
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) // 有可能a > b + c, 铺满两边再在中间乱放
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, 只可能有两种情况
else if(a==b*c) // 情况1: 有一个是1了, 往上移动1个
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 //情况2: 有一个是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是z轴的高度
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
题目链接
乱搞或线段树+set
题意:给出n个操作,
操作1表示建立一个位于(x,y)且半径为y的靶子。
操作2表示往(x,y)处开一枪。
要求在每次开枪的时候,给出枪是否命中了靶子,若命中了则输出靶子的编号,并且删除这个靶子,若没有命中则输出-1
补
用set存左右边界然后二分直接找两边的好像不太行
然后换思路二分找(当前x-最大半径)之后的圆 check
但是找到最后会 t 所以只要找到的圆心的
x
x
x 小于(当前x+最大半径)就可以了
线段树做法
#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); //直接找大于等于 x 会漏
bool flag=0;
while(it!=se.end())
node pp=(*it);
if(pp.x>x+mr) break; //没有了就break
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
题目链接
树链剖分+LCA+线段树
题意:给出一棵树和一组操作,操作的格式是给出
u
v
uv
uv两个节点,并将该节点所确定的路径上的节点全部加入到一个新的集合里面去。
如果所有的集合中任意两个均满足,要么互相包含,要么不相交,则输出Yes,否则输出No
未补
贴上佬的代码
#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) 2017-2018 ACM-ICPC, NEERC, Moscow Subregional Contest
(寒假开黑gym)2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)
训练20191007 2017-2018 ACM-ICPC Latin American Regional Programming Contest
2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)
2017-2018 ACM-ICPC Latin American Regional Programming Contest
2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)题解+补题