模拟赛小结:2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)
比赛链接:传送门
本场我们队过的题感觉算法都挺简单的,不知道为啥做的时候感觉没有很顺利。
封榜后7题,罚时1015。第一次模拟赛金,虽然是北欧的区域赛,但还是有点开心的。
Problem B Best Relay Team 00:49 (+2) Solved by xk
排序后简单模拟一下题意即可。
xk说他要背个锅。
代码:
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#ifdef ONLINE_JUDGE
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#else
#define fast
#endif
#define forn(i, n) for(int i = 0; i < (n); i++)
#define forab(i, a, b) for(int i = (a); i <= (b); i++)
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; const int maxn = + ; string s[maxn];
db a[maxn], b[maxn]; int main()
{
int n;
fast;
cin >> n;
forn(i, n)
{
cin >> s[i] >> a[i] >> b[i];
}
vector<pair<db, int> > va, vb;
forn(i, n)
{
va.push_back(mp(a[i], i));
vb.push_back(mp(b[i], i));
}
sort(va.begin(), va.end());
sort(vb.begin(), vb.end());
db ans = 1e100;
int aid = ;
int isin = ;
forn(i, n)
{
db temp = a[i];
int in3 = ;
forn(j, )
{
if(i == vb[j].second) {
in3 = ;
continue;
}
temp += vb[j].first;
}
if(in3) temp += vb[].first;
if(temp < ans) {
aid = i;
isin = in3;
ans = temp;
}
}
cout << ans << endl;
cout << s[aid] << endl;
forn(i, )
{
if(aid != vb[i].second)
cout << s[vb[i].second] << endl;
}
if(isin)
cout << s[vb[].second] << endl;
return ;
}
Problem D Distinctive Character 03:52 (+) Solved by xk (bfs)
类似于bfs的想法,每个状态走一步可以到达的状态是二进制与其有1位不同的状态。最后一个出队的点就是答案。所有状态空间是$2^{20} ≈ 10^{6}$。
我和lh盯了好久没有思路,几乎要弃题了。结果xk一拍脑门就来了一发bfs就过了。
代码:$O(2^{k})$
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#include <bitset>
#ifdef ONLINE_JUDGE
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#else
#define fast
#endif
#define forn(i, n) for(int i = 0; i < (n); i++)
#define forab(i, a, b) for(int i = (a); i <= (b); i++)
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; const int maxk = ( << ) + ;
const int maxn = 1e5 + ; int dep[maxk];
int a[maxn]; int main()
{
fast;
int n, k;
cin >> n >> k;
forn(i, n)
{
char s[];
cin >> s;
forn(j, k)
{
a[i] = a[i] * + s[j] - '';
}
}
sort(a, a + n);
n = unique(a, a + n) - a;
queue<int> q;
memset(dep, -, sizeof(dep));
forn(i, n)
{
q.push(a[i]);
dep[a[i]] = ;
}
int ans = a[];
while(!q.empty())
{
int x = q.front(); q.pop();
forn(i, k)
{
int y = x ^ ( << i);
// cout << bitset<5>(x) << ' ' << bitset<5>(y) << ' ' << dep[y] << endl;
if(dep[y] == -)
{
dep[y] = dep[x] + ;
if(dep[y] > dep[ans])
{
ans = y;
}
q.push(y);
}
// cout << bitset<5>(x) << ' ' << bitset<5>(y) << ' ' << dep[y] << endl;
}
}
for(int i = k - ; i >= ; i--)
{
cout << (bool)(ans & ( << i));
}
return ;
}
Problem E Emptying the Baltic 02:25(+) Solved by Dancepted (优先队列 + bfs)
每次挑海拔最低的点进行bfs,每个点的海拔更新为max(原来的海拔,bfs过来的点的海拔)。因为每次选的是最低的点进行bfs,所以能保证每个点第一次被更新时一定是最优的。
看了半个多小时才看出来做法,太菜了qwq。
代码:$O(hw)$
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 505
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; /** fast read **/
template <typename T>
inline void read(T &x) {
x = ; T fg = ; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -;
ch = getchar();
}
while (isdigit(ch)) x = x*+ch-'', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = ; char c[]; if (x < ) putchar('-'), x = -x;
do{++len; c[len] = x% + '';} while (x /= );
for (int i = len; i >= ; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); } const int dx[] = {, , , , -, -, -, };
const int dy[] = {, , -, -, -, , , }; struct Node{
int x, y;
ll dep;
bool operator < (const Node& x) const {
return dep > x.dep;
}
};
ll pool[N][N];
bool vis[N][N];
priority_queue <Node> Q;
int main() {
int n, m; cin >> n >> m;
for (int i = ; i <= n; i++) {
for (int j = ; j <= m; j++)
read(pool[i][j]);
}
Node st;
read(st.x, st.y);
st.dep = pool[st.x][st.y];
Q.push(st);
while (!Q.empty()) {
Node tmp = Q.top(); Q.pop();
if (vis[tmp.x][tmp.y])
continue;
vis[tmp.x][tmp.y] = true;
pool[tmp.x][tmp.y] = tmp.dep;
for (int i = ; i < ; i++) {
Node nxt = Node{tmp.x + dx[i], tmp.y + dy[i]};
if (nxt.x <= || nxt.x > n || nxt.y <= || nxt.y > m)
continue;
if (vis[nxt.x][nxt.y])
continue;
nxt.dep = max(pool[nxt.x][nxt.y], tmp.dep);
Q.push(nxt);
}
}
ll ans = ;
for (int i = ; i <= n; i++) {
for (int j = ; j <= m; j++) {
if (pool[i][j] < )
ans -= pool[i][j];
}
}
cout << ans << endl;
return ;
}
Problem G Galactic Collegiate Programming Contest 02:16(+) Solved by xk (模拟)
比赛中的大致思路是开M个set,对应每个解题数的队伍。如果如果其他队过题,观察题数/罚时是否超过了1号队。如果是1号队过题,算上过题数和罚时之后,在对应的题数里面暴力找1号队的排名。
复杂度的期望是O(nlogn)的,常数比较大,不过关系不大。
代码:$O(nlogn)$
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#ifdef ONLINE_JUDGE
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#else
#define fast
#endif
#define forn(i, n) for(int i = 0; i < (n); i++)
#define forab(i, a, b) for(int i = (a); i <= (b); i++)
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; const int maxn = 1e5 + ; struct node
{
int solve, time;
bool operator < (const node & a) const
{
if(solve != a.solve) return solve < a.solve;
return time > a.time;
}
}; int n, m;
set<pair<int, int> > s[maxn];
int sum[maxn];
int solve[maxn], penal[maxn]; int main()
{
fast;
cin >> n >> m;
int ans = ;
forab(i, , n)
{
s[].insert(mp(, i));
sum[i] = n;
}
for (int i = ; i <= m; i++)
{
int t, p;
cin >> t >> p;
s[solve[t]].erase(mp(penal[t], t));
sum[solve[t]]--;
solve[t]++; penal[t] += p;
s[solve[t]].insert(mp(penal[t], t)); if(t == )
{
auto it = s[solve[t]].begin();
ans = n - sum[solve[t]] + ;
while(it->first < penal[t])
{
ans++;
it++;
}
}
else
{
node t1 = node{solve[], penal[]};
node before = node{solve[t] - , penal[t] - p};
node now = node{solve[t], penal[t]};
if(!(t1 < before) && t1 < now)
{
ans++;
}
}
cout << ans << endl;
}
return ;
}
/*
3 4
2 7
3 5
1 6
1 9
*/
赛后观摩了一下claris的博客,有个更好的模拟。
维护一个set表示比1号队排名严格靠前的队伍。其他队过题就考虑是否加入set,1队过题就考虑在set中删除被1队超过的队伍。
代码:$O(nlogn)$
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <stdio.h>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; /** fast read **/
template <typename T>
inline void read(T &x) {
x = ; T fg = ; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -;
ch = getchar();
}
while (isdigit(ch)) x = x*+ch-'', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = ; char c[]; if (x < ) putchar('-'), x = -x;
do{++len; c[len] = x% + '';} while (x /= );
for (int i = len; i >= ; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); } struct Node{
int id, cnt, penalty;
bool operator < (const Node& x) const {
if(cnt == x.cnt) {
if (penalty == x.penalty)
return id < x.id;
return penalty < x.penalty;
}
return cnt > x.cnt;
}
};
set<Node> S;
set<Node> :: iterator it, jt;
int cnt[N], penalty[N];
int main() {
int n, m; cin >> n >> m;
Node concern = Node{, , };
for (int i = ; i <= m; i++) {
int t, p; read(t, p);
if (t == ) {
concern.cnt++;
concern.penalty += p;
it = S.lower_bound(concern);
while (it != S.end()) {
jt = it++;
S.erase(jt);
}
}
else {
Node pre = Node{t, cnt[t], penalty[t]};
cnt[t]++, penalty[t] += p;
Node nxt = Node{t, cnt[t], penalty[t]};
if (pre < concern)
S.erase(pre);
if (nxt < concern)
S.insert(nxt);
}
printf("%d\n", sz(S) + );
}
return ;
}
Problem I Import Spaghetti 01:31(+) Solved by lh (floyd)
实际上就是找出一个有向图的最小环。$dis_{i,i}$初始化为INF,跑一下floyd之后,找$dis_{i,i}$的最小值。
代码:$O(n^{3})$
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
using namespace std;
int n, dis[][], k, road[][];
map<string, int> id;
map<int, string> in;
string s;
int final[N], tot = ;
void solve(int l, int r)
{
if(dis[l][r] == )
return;
solve(l, road[l][r]), final[++tot] = road[l][r], solve(road[l][r], r);
}
int ac()
{
fast;
cin >> n;
memset(dis, 0x3f, sizeof(dis));
for(int i = ; i <= n; ++i)
cin >> s, id[s] = i, in[i] = s;
for(int i = ; i <= n; ++i)
{
cin >> s >> k;
char c;
for (int j = ; j <= k; ++j)
{
cin >> s >> s;
while (s[s.size() - ] == ',')
{
s.pop_back();
dis[i][id[s]] = ;
cin >> s;
}
dis[i][id[s]] = ;
}
}
for (int i = ;i <= n; ++i)
for (int j = ;j <= n; ++j)
for (int k = ;k <= n; ++k)
{
if (dis[j][k] > dis[j][i] + dis[i][k])
dis[j][k] = dis[j][i] + dis[i][k], road[j][k] = i;
}
int ans = ;
bool flag = false;
for (int i = ;i <= n; ++i)
{
if (dis[i][i] != INF)
{
flag = true;
if (dis[ans][ans] > dis[i][i])
ans = i;
}
}
if (!flag)
{
puts("SHIP IT");
return ;
}
solve(ans, ans), cout << in[ans];
for (int i = ; i <= tot; ++i)
cout << " " << in[final[i]];
}
int main()
{
ac();
return ;
}
/*
4
a b c d
a 1
import d, b, c
b 2
import d
import c
c 1
import c
d 0
*/
Problem J Judging Moose 00:12 (+) Solved by Dancepted
printf级别的签到。12分钟才过是因为电脑网速太慢打不开pdf。
代码:
Problem K Kayaking Trip 04:30 (-2) Solved by Dancepted (二分答案+贪心)
答案单调是显然的。贪心就是对每艘船选择最小的选手能力值的组合,使得这个组合与船的系数的乘积,能不小于答案。
读完题我就猜是这么写的,但是正确性有点不确定。然后lh想了个假的暴力交上去wa了两发后,被我hack了。
代码(附一个样例):$O((b+n+e)log(2 * c_{max} * s_{max})$
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; /** fast read **/
template <typename T>
inline void read(T &x) {
x = ; T fg = ; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -;
ch = getchar();
}
while (isdigit(ch)) x = x*+ch-'', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = ; char c[]; if (x < ) putchar('-'), x = -x;
do{++len; c[len] = x% + '';} while (x /= );
for (int i = len; i >= ; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); } int sum = ;
int cnt[], val[], boat[N];
int ccnt[];
bool check(int mid) {
for (int i = ; i < ; i++)
ccnt[i] = cnt[i];
for (int i = ; i < sum/; i++) {
int pa = , pb = ;
for (int a = ; a < ; a++) if (ccnt[a]) {
ccnt[a]--;
for (int b = a; b < ; b++) if (ccnt[b]) {
ccnt[b]--;
if (mid <= boat[i] * (val[a] + val[b]) && val[a] + val[b] < val[pa] + val[pb]) {
pa = a;
pb = b;
}
ccnt[b]++;
}
ccnt[a]++;
}
if (mid > boat[i] * (val[pa] + val[pb]))
return false;
if (pa != pb) {
if (ccnt[pa] && ccnt[pb]) {
ccnt[pa]--, ccnt[pb]--;
}
else
return false;
}
else if (pa == pb) {
if (ccnt[pa] >= ) {
ccnt[pa] -= ;
}
else
return false;
}
}
return true;
} int main() {
for (int i = ; i < ; i++)
read(cnt[i]),
sum += cnt[i];
for (int i = ; i < ; i++)
read(val[i]);
for (int i = ; i < sum/; i++) {
read(boat[i]);
}
sort(boat, boat + sum/);
int l = , r = INF, ans = ;
// int l = 0, r = 5000, ans = 0;
while (l <= r) {
int mid = (l+r) >> ;
if (check(mid)) {
ans = max(ans, mid);
l = mid+;
}
else {
r = mid-;
}
}
cout << ans << endl;
return ;
}
/*
4 4 4
1 2 5
42 60 70 105 140 210
*/
总结:
封榜的时候已经没事干了,我抓起键盘想着莽一发K的二分+贪心,居然真的就过了。模拟赛拿金成就get√。
第一次模拟赛金着实开心,但是想了想这场打得也不是很舒服,也没有发挥得很好。前期开题各种不顺,但是看排名就是掉不下去。可能是这个赛区的选手弱了吧。
上海站还有10天不到的时间,理论上是能冲到银首的位置的。就看能不能开出一道金牌题了。
接下来几天看看进阶指南,学点没学过的算法,打完ccpcf回来再练几场模拟赛,应该就差不多了。
2019冲鸭!
模拟赛小结:2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)的更多相关文章
- Codeforces Gym101572 B.Best Relay Team (2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017))
2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) 今日份的训练,题目难度4颗星,心态被打崩了,会的算法太少了,知 ...
- 2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) Solution
A - Airport Coffee 留坑. B - Best Relay Team 枚举首棒 #include <bits/stdc++.h> using namespace std; ...
- 2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)
A. Airport Coffee 设$f_i$表示考虑前$i$个咖啡厅,且在$i$处买咖啡的最小时间,通过单调队列优化转移. 时间复杂度$O(n)$. #include<cstdio> ...
- Codeforces Gym101572 G.Galactic Collegiate Programming Contest (2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017))
Problem G Galactic Collegiate Programming Contest 这个题题意读了一会,就是几个队参加比赛,根据实时的信息,问你1号队的实时排名(题数和罚时相同的时候并 ...
- Codeforces Gym101572 J.Judging Moose (2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017))
Problem J Judging Moose 这个题是这里面最简单的一个题... 代码: 1 //J 2 #include <stdio.h> 3 #include <math. ...
- (寒假GYM开黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)
layout: post title: 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) author: &qu ...
- 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)- D. Delivery Delays -二分+最短路+枚举
2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)- D. Delivery Delays -二分+最短路+枚举 ...
- 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)-E. Explosion Exploit-概率+状压dp
2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)-E. Explosion Exploit-概率+状压dp [P ...
- 模拟赛小结:2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)
比赛链接:传送门 两个半小时的时候横扫了铜.银区的所有题,签到成功混进金区.奈何后面没能开出新的题. 最后一个小时的时候xk灵机一动想出了D题的做法,讨论了一波感觉可行,赶紧去敲.结束前2分钟终于过了 ...
随机推荐
- ubuntu安装dockers和images:dvwa
docker安装 安装前需要更新系统 apt-get update apt-get upgrade apt-get install docker.io 安装完之后就可以试下: docker docke ...
- DDoS攻击的几种类型
DDoS攻击的几种类型 随着网络攻击的简单化,如今DDoS攻击已经不止出现在大型网站中,就连很多中小型网站甚至是个人网站往往都可能面临着被DDoS攻击的的风险.或许很多站长对DDoS攻击并不是很了 ...
- 【VS开发】static、extern分析总结
引用请注明出处:http://blog.csdn.net/int64ago/article/details/7396325 对于写了很多小程序的人,可能static和extern都用的很少,因为sta ...
- 前端数据Mock
参考链接:https://www.clloz.com/programming/front-end/js/2019/05/10/data-mock/?utm_medium=hao.caibaojian. ...
- js ajax跨域被阻止 CORS 头缺少 'Access-Control-Allow-Origin'(转)
今天ajax请求域名的时候出现 已阻止跨源请求:同源策略禁止读取位于 http://www.zuimeimami.com*****的远程资源.(原因:CORS 头缺少 'Access-Control- ...
- linux分区知识
1.硬盘使用前,一般要分区,格式化(创建文件系统)--存放数据(极端情况下,可以不分区) 2.分区: 主分区. 扩展分区.逻辑分区 主分区+拓展分区的数量<=4,其中一个主分区可以用一个拓展分区 ...
- C#追加日志文件
追加日志文件 using System; using System.IO; class DirAppend { public static void Main() { using (StreamWri ...
- java导入导出Excel文件
package poi.excel; import java.io.IOException; import java.io.InputStream; import java.io.OutputStre ...
- 【洛谷P1816】忠诚——ST表做法
看了两个小时RMQ并位运算,对二进制勉勉强强有了个初步了解,不能说精通(可能今年CSP前都做不到精通),但是记熟板子做做题还是没有问题的 以下是正式题解,相信你看过了题目,我介绍的是ST表的做法(很简 ...
- C++多线程基础学习笔记(三)
一.detach()大坑 上一篇随笔(二)中提到detach()是用来分离主线程和子线程的,那么需要考虑一个问题,就是如果主线程跑完了,主线程中定义的变量就会被销毁(释放内存),这时回收变量仍作为参数 ...