2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) 日常训练
题目大意:按时间顺序出现靶子和射击一个位置,靶子的圆心为(x, y)半径为r,即圆与x轴相切,靶子不会重叠,靶子被击中后消失,
每次射击找出哪个靶子被射中,或者没有射中靶子。
思路:关键点在于,圆都与x轴相切,那么我们能发现,如果射击在(x, y) 这个点,包含它的圆只可能是它左边第一个直径>= y的圆c1,
或者是它右边第一个直径 >=y 的圆c2,因为在c1 和 c2之间的圆不可能覆盖到(x, y), 因为它们的直径小于y,在c1左边和c2右边的圆
通过画图我们也能得出不肯能包含(x, y),那么每次射击我们只需要check两个圆就好了。
找圆的过程能用线段树维护,加入一个圆就在线段树对应的x的位置的值变成2*r,然后通过二分用线段树找圆,最后判一下是否在圆内。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int> using namespace std; const int N = 2e5 + ;
const int M = 1e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +; int n, tot, mx[N << ], X[N], hs[N]; struct Qus {
int op, x, y;
} qus[N]; void update(int pos, int v, int l, int r, int rt) {
if(l == r) {
mx[rt] = v;
return;
} int mid = l + r >> ;
if(pos <= mid) update(pos, v, l, mid, rt << );
else update(pos, v, mid + , r, rt << | ); mx[rt] = max(mx[rt << ], mx[rt << | ]);
} int getMx(int L, int R, int l, int r, int rt) {
if(l >= L && r <= R) return mx[rt]; int mid = l + r >> , ans = ; if(L <= mid) ans = max(ans, getMx(L, R, l, mid, rt << ));
if(R > mid) ans = max(ans, getMx(L, R, mid + , r, rt << | ));
return ans;
} bool check(int x, int y, int id) {
LL dis1 = 1ll * qus[id].y * qus[id].y;
LL dis2 = 1ll * (x - qus[id].x) * (x - qus[id].x) + 1ll * (y - qus[id].y) * (y - qus[id].y);
return dis1 > dis2;
} int main() { scanf("%d", &n); for(int i = ; i <= n; i++) {
scanf("%d%d%d", &qus[i].op, &qus[i].x, &qus[i].y);
hs[++tot] = qus[i].x;
} sort(hs + , hs + + tot);
tot = unique(hs + , hs + + tot) - hs - ; for(int i = ; i <= n; i++) {
int op = qus[i].op, x = qus[i].x, y = qus[i].y; int pos = lower_bound(hs + , hs + + tot, x) - hs; if(op == ) {
X[pos] = i;
update(pos, * y, , tot, );
} else {
int l = , r = pos, ret = -;
while(l <= r) {
int mid = l + r >> ;
if(getMx(mid, pos, , tot, ) >= y) ret = mid, l = mid + ;
else r = mid - ;
} if(ret != - && check(x, y, X[ret])) {
printf("%d\n", X[ret]);
update(ret, , , tot, );
continue;
} l = pos, r = tot, ret = -;
while(l <= r) {
int mid = l + r >> ;
if(getMx(pos, mid, , tot, ) >= y) ret = mid, r = mid - ;
else l = mid + ;
} if(ret != - && check(x, y, X[ret])) {
printf("%d\n", X[ret]);
update(ret, , , tot, );
continue;
} puts("-1"); }
}
return ;
}
题目大意:问长宽高为a, b, c的立方体,能不能用n * m的纸折出来。
思路:暴力枚举判断。。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int> using namespace std; const int N = + ;
const int M = 1e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +; int n, m, a[], id[]; bool check(int x, int y) {
if(x <= n && y <= m) return true;
if(x <= m && y <= n) return true;
return false;
}
int main() {
scanf("%d%d%d", &a[], &a[], &a[]);
id[] = , id[] = , id[] = ;
scanf("%d%d", &n, &m); sort(a, a + ); do {
int x = a[id[]], y = a[id[]], z = a[id[]]; if(check( * z + x, * y + * z)) {
puts("Yes");
return ;
} if(check(x + y + z, * x + y + z)) {
puts("Yes");
return ;
} if(check( * z + x, x + * y + z)) {
puts("Yes");
return ;
} if(check( * y + x + z, x + z)) {
puts("Yes");
return ;
}
} while(next_permutation(id, id + ));
puts("No");
return ;
} /*
2z + x
2y + 2z x + y + z
2x + y + z 2z + x
x + 2y + z */
题目大意:给你一个 n 个点 m (m >= 2 * n)条边的有向图,且原图为一个强连通分量,要求你选出2 * n条边,其他的删掉仍然是一个
强连通分量。
思路:比赛的时候我没想到,队友想出来的。。 用1号点跑一遍图,建反边用1号点再跑一次就好了。 应该挺听容易想到的,题目说2 * n
应该想到由两个树组成。
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; vector<pair<int,int> >v[N],rev[N];
pii p[N];
bool vis[N],used[N];
void dfs(int u)
{
vis[u]=;
for(int i=;i<v[u].size();i++)
{
int x=v[u][i].fi;
if(!vis[x])
{
used[v[u][i].se]=;
dfs(x);
}
}
}
void dfs1(int u)
{
vis[u]=;
for(int i=;i<rev[u].size();i++)
{
int x=rev[u][i].fi;
if(!vis[x])
{
used[rev[u][i].se]=;
dfs1(x);
}
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)v[i].clear(),rev[i].clear();
for(int i=;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
v[x].pb(mp(y,i));
rev[y].pb(mp(x,i));
p[i]=mp(x,y);
used[i]=;
}
memset(vis,,sizeof vis);
dfs();
memset(vis,,sizeof vis);
dfs1();
int sum=;
for(int i=;i<m;i++)
if(used[i])
sum++;
int now=*n-sum;
for(int i=;i<m;i++)
{
if(!used[i]&&now)
{
now--;
used[i]=;
}
}
for(int i=;i<m;i++)
if(!used[i])
printf("%d %d\n",p[i].fi,p[i].se);
}
return ;
}
/******************** ********************/
题目大意:给你三视图的每个面能看见的方块个数a, b, c,然后构造出这样的图形。
思路:一起想了挺久的,三维立体很难实现,我们就考虑把所有点放一个面里面,构成图形的个数就是max(a, b, c),
斜着放三面个数都加一,横着放两面个数加一,填补空缺一个面加一,构造一下。细节挺多的。。。
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; int a[], b[]; struct point{
int x,y,z;
};
int ok[N][N];
void solve(int x,int y,int z){
vector<point> v;
vector<point> ans;
for(int i=;i<x;i++)
v.pb({,i,i});
for(int i=x;i<y;i++)
v.pb({,x-,i});
for(int i=;i<v.size();i++)ok[v[i].y][v[i].z]=;
int now=z-y;
for(int i=;i<x;i++)
{
for(int j=;j<y;j++)
{
if(!ok[i][j]&&now)
{
v.pb({,i,j});
ok[i][j]=;
now--;
}
}
}
if(now!=){puts("-1");return ;}
if(b[]==a[]&&b[]==a[]&&b[]==a[])
{
for(int i=;i<v.size();i++)swap(v[i].x,v[i].y);
}
else if(b[]==a[]&&b[]==a[]&&b[]==a[])
{
for(int i=;i<v.size();i++)swap(v[i].y,v[i].z);
}
else if(b[]==a[]&&b[]==a[]&&b[]==a[])
{
for(int i=;i<v.size();i++)
{
swap(v[i].x,v[i].z);
swap(v[i].y,v[i].z);
}
}
else if(b[]==a[]&&b[]==a[]&&b[]==a[])
{
for(int i=;i<v.size();i++)
{
swap(v[i].x,v[i].y);
swap(v[i].y,v[i].z);
}
}
else if(b[]==a[]&&b[]==a[]&&b[]==a[])
{
for(int i=;i<v.size();i++)
{
swap(v[i].x,v[i].z);
}
}
printf("%d\n",v.size());
for(int i=;i<v.size();i++)
printf("%d %d %d\n",v[i].x,v[i].y,v[i].z);
}
int main(){ for(int i = ; i < ; i++) {
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(a, a + );
solve(a[],a[],a[]);
return ;
}
/******************** ********************/
队友写的水题,不知道啥意思。
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-;
const int N=+,maxn=+,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; multiset<int>p;
int a[N];
int ans[N];
int main()
{
int n;
scanf("%d",&n);
for(int i=,x;i<=n;i++)
{
scanf("%d",&x);
if(x>)a[x]++;
else if(x==)p.insert(i);
else
{
if(a[-x]>)a[-x]--;
else if(p.size()!=)
{
// printf("--%d\n",*p.begin());
ans[*p.begin()]=-x;
p.erase(p.begin());
}
else return *puts("No");
}
}
while(p.size()!=)ans[*p.begin()]=,p.erase(p.begin());
puts("Yes");
for(int i=;i<=n;i++)
if(ans[i]!=)
printf("%d ",ans[i]);
puts("");
return ;
}
/******************** ********************/
补题****************************************************************************
题目大意,有若干个L形连通块,两边长为n,有一个重叠, 问你最少用几个能把(0 , 0)和(a, b)连起来, L形的物件不能有交叉。
思路:分类讨论贪心,分为一下几种情况。
1.a - x < n && b - y < n 用一个L就能连通
2.a - x > n && b - y > n 贪心地继续连在前一个的末端
3.a - x > n && b - y < n y这维不用贪了,贪x这维。
4.与3相反。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int> using namespace std; const int N = 2e5 + ;
const int M = 1e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +; int T;
LL a, b, n;
bool flag = false;
vector<pair<pair<LL, LL>, pair<LL, LL> > > ans; void dfs(LL x, LL y) {
if(a - x < n && b - y < n) {
if(!flag) {
int x1 = x - (x + n - - a);
int y1 = y;
int x2 = a;
int y2 = y + n - ;
ans.push_back(mk(mk(x2, y2), mk(x1, y1)));
return;
} else {
int x2 = x;
int y2 = y - (y + n - - b);
int x1 = x + n - ;
int y1 = b;
ans.push_back(mk(mk(x2, y2), mk(x1, y1)));
}
return;
} if(b - y < n) {
ans.push_back(mk(mk(x + n - , y - n + ), mk(x, y)));
flag = true;
dfs(x + n, y);
return;
} if(a - x < n) {
ans.push_back(mk(mk(x, y), mk(x - n + , y + n - )));
flag = false;
dfs(x, y + n);
return;
} if(a - x >= n && b - y >= n) {
ans.push_back(mk(mk(x + n - , y + n - ), mk(x, y)));
if(abs(a - x) >= abs(b - y)) flag = true, dfs(x + n, y + n - );
else flag = false, dfs(x + n - , y + n);
return;
} } int main() {
scanf("%d", &T);
while(T--) {
ans.clear();
scanf("%lld%lld%lld", &a, &b, &n);
int x = a, y = b;
if(a < ) a = -a;
if(b < ) b = -b; dfs(, ); for(int i = ; i < ans.size(); i++) {
if(a != x) ans[i].fi.fi = -ans[i].fi.fi, ans[i].se.fi = -ans[i].se.fi;
if(b != y) ans[i].fi.se = -ans[i].fi.se, ans[i].se.se = -ans[i].se.se;
} printf("%d\n", (int) ans.size()); for(int i = ; i < ans.size(); i++) {
printf("%lld %lld %lld %lld\n", ans[i].fi.fi, ans[i].fi.se, ans[i].se.fi, ans[i].se.se);
}
}
return ;
} /*
1
4 1 3
*/
2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) 日常训练的更多相关文章
- 2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)
2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) A 题意:有 n 个时刻 ...
- ACM ICPC 2010–2011, Northeastern European Regional Contest St Petersburg – Barnaul – Tashkent – Tbilisi, November 24, 2010
ACM ICPC 2010–2011, Northeastern European Regional Contest St Petersburg – Barnaul – Tashkent – Tbil ...
- Editing 2011-2012 ACM-ICPC Northeastern European Regional Contest (NEERC 11)
NEERC 11 *wiki链接[[https://acm.ecnu.edu.cn/wiki/index.php?title=2011-2012_ACM-ICPC_Northeastern_Europ ...
- 2012-2013 ACM-ICPC Northeastern European Regional Contest (NEERC 12)
Problems # Name A Addictive Bubbles1 addictive.in / addictive.out 2 s, 256 MB x438 B Blin ...
- 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15)C - Cactus Jubilee
题意:给一颗仙人掌,要求移动一条边,不能放在原处,移动之后还是一颗仙人掌的方案数(仙人掌:无向图,每条边只在一个环中),等价于先删除一条边,然后加一条边 题解:对于一颗仙人掌,分成两种边,1:环边:环 ...
- 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02) H Heroes Of Might And Magic (隐含dp)
问题是求一个方案,实际隐含一个dp.法力是递减的,所以状态是DAG,对于一个确定的状态,我们贪心地希望英雄的血量尽量大. 分析:定义状态dp[i][p][h]表示是已经用了i的法力值,怪兽的位置在p, ...
- 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02) A Amusing Numbers (数学)
其实挺简单的.先直接算出之前已经排在k这个数前面的数字.比如543是三位的,那么100~543都是可以的,两位的10~54. 如果还需要往前面补的话,那么依次考虑1000~5430,5430是上界不能 ...
- 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15)
NEERC 15 题解1 题解2 官方题解
- 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02)
B Bricks 计算几何乱搞 题意: 给你个立方体,问你能不能放进一个管道里面. 题解: 这是一道非常迷的题,其问题在于,你可以不正着放下去,你需要斜着放.此时你需要枚举你旋转的角度,来判断是否可行 ...
随机推荐
- Linux 守护进程创建原理及简易方法
1:什么是Linux下的守护进程 Linux daemon是运行于后台常驻内存的一种特殊进程,周期性的执行或者等待trigger执行某个任务,与用户交互断开,独立于控制终端.一个守护进程的父进程是in ...
- hadoop压缩和解压
最近有一个hadoop集群上的备份需求.源文件有几百G,如果直接复制太占用磁盘空间.将文件从hadoop集群下载到本地,压缩之后再上传到hadoop则太耗时间.于是想到能否直接在HDFS文件系统上进行 ...
- SSH客户端,FinalShell服务器管理,远程桌面加速软件,支持Windows,Mac OS X,Linux,版本2.6.3.1
FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发,运维工具,充分满足开发,运维需求. 用户QQ群 342045988 Windows版下载地址:http:/ ...
- 解决华为手机用rem单位,内容超出屏幕宽度问题
在H5手机页面上,用rem单位布局,配合js计算出一个根节点的font-size(原理是屏幕宽度乘以一个固定比例,如1/100),之后页面中所有的px全都换算成了rem单位来写,优点是能适配各种不同屏 ...
- [USACO06NOV] Roadblocks
https://www.luogu.org/problem/show?pid=2865 题目描述 Bessie has moved to a small farm and sometimes enjo ...
- vue中的表单异步校验方法封装
在vue项目的开发中,表单的验证必不可少,在开发的过程中,用的是vue+iview的一套,我们知道iview的表单验证是基于async-validator,对于async-validator不熟悉的可 ...
- js_!和!!的使用
js中有些特殊的数据(“” 0 null undefined NaN),请求后台返回的数据中往往都有一些这样的数据,需要对这些数据进行过滤. 过滤代码 var a = 0;//0 "&quo ...
- 基于Android的简单聊天工具-服务器端
1.数据库用的mysql,一共有3张表,一张用户表user.一张朋友列表friend和一张消息表message. 1 User table 用户表 uid 主键自动生成 userName 昵称 use ...
- 【DataScience学习笔记】Coursera课程《数据科学家的工具箱》 约翰霍普金斯大学——Week3 Conceptual Issues课堂笔记
Coursera课程<数据科学家的工具箱> 约翰霍普金斯大学 Week3 Conceptual Issues Types of Questions Types of Data Scienc ...
- linux pthread【转】
转自:http://www.cnblogs.com/alanhu/articles/4748943.html Posix线程编程指南(1) 内容: 一. 线程创建 二.线程取消 关于作者 线程创 ...