ACM ICPC, JUST Collegiate Programming Contest (2018) Solution
A:Zero Array
题意:两种操作, 1 p v 将第p个位置的值改成v 2 查询最少的操作数使得所有数都变为0 操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能变为负数
思路:考虑第二种操作,显然,最少的操作数肯定是不同数的个数 用map 记录,特殊注意0的存在
#include <bits/stdc++.h> using namespace std; #define N 100010 unordered_map <int, int> mp; int t, n, q; int arr[N]; int main()
{
cin.tie();
cout.tie();
ios::sync_with_stdio(false);
cin >> t;
while (t--)
{
cin >> n >> q;
mp.clear();
for (int i = ; i <= n; ++i)
{
cin >> arr[i];
mp[arr[i]]++;
}
int op, p, v;
while (q--)
{
cin >> op;
if (op == )
{
cin >> p >> v;
if (mp[arr[p]] == )
{
mp.erase(arr[p]);
}
else
{
mp[arr[p]]--;
}
mp[v]++;
arr[p] = v;
}
else
{
mp[]++;
cout << mp.size() - << endl;
}
}
}
return ;
}
B:New Assignment
题意:给出n个人,有男生有女生,每个人有权值,进行分组,一个男的可以一组,一个女的可以一组,一男一女可以一组当且仅当他们的权值的最大公约数大于1,求最少的分组数量
思路:优先让一男一女分组,让可以一起分组的男女连边,跑二分匹配或者最大流,建图的时候注意不能够直接GCD,这样常数比较大,我们分解质因数卡卡常就可以过去
二分图匹配:
#include <bits/stdc++.h> using namespace std; #define N 10010
#define M 1000010
#define INF 0x3f3f3f3f vector <int> G[N];
int uN, vN;
int Mx[N], My[N];
int dx[N], dy[N];
int dis;
bool used[N]; inline bool SearchP()
{
queue <int> Q;
dis = INF;
memset(dx, -, sizeof dx);
memset(dy, -, sizeof dy);
for (int i = ; i < uN; ++i)
if (Mx[i] == -)
{
Q.push(i);
dx[i] = ;
}
while (!Q.empty())
{
int u = Q.front();
Q.pop();
if (dx[u] > dis) break;
int sz = G[u].size();
for (int i = ; i < sz; ++i)
{
int v = G[u][i];
if (dy[v] == -)
{
dy[v] = dx[u] + ;
if (My[v] == -) dis = dy[v];
else
{
dx[My[v]] = dy[v] + ;
Q.push(My[v]);
}
}
}
}
return dis != INF;
} inline bool DFS(int u)
{
int sz = G[u].size();
for (int i = ; i < sz; ++i)
{
int v = G[u][i];
if (!used[v] && dy[v] == dx[u] + )
{
used[v] = true;
if (My[v] != - && dy[v] == dis) continue;
if (My[v] == - || DFS(My[v]))
{
My[v] = u;
Mx[u] = v;
return true;
}
}
}
return false;
} inline int MaxMatch()
{
int res = ;
memset(Mx, -, sizeof Mx);
memset(My, -, sizeof My);
while (SearchP())
{
memset(used, false, sizeof used);
for (int i = ; i < uN; ++i)
if (Mx[i] == - && DFS(i))
res++;
}
return res;
} int t, n; int arr[N], brr[N]; vector <int> pr[M], fac[M]; inline void Init()
{
for (int i = ; i <= ; ++i)
if (pr[i].empty())
for (int j = i; j <= ; j += i)
pr[j].emplace_back(i);
} int a[N], b[N];
map <int, bool> mp; int main()
{
Init();
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = ; i <= n; ++i) scanf("%d", arr + i);
uN = , vN = ;
char c;
for (int i = ; i <= n; ++i)
{
scanf(" %c", &c);
if (c == 'F')
{
a[uN] = arr[i];
for (int j = , len = pr[arr[i]].size(); j < len; ++j)
{
int x = pr[arr[i]][j];
fac[x].emplace_back(uN);
}
G[uN].clear();
uN++;
}
else
{
b[vN] = arr[i];
vN++;
}
}
for (int i = ; i < vN; ++i)
{
mp.clear();
for (int j = , len = pr[b[i]].size(); j < len; ++j)
{
int x = pr[b[i]][j];
for (int k = , lenn = fac[x].size(); k < lenn; ++k)
{
int id = fac[x][k];
if (mp[id] == false)
{
mp[id] = true;
G[id].emplace_back(i);
}
}
}
}
printf("%d\n", n - MaxMatch());
for (int i = ; i < uN; ++i)
{
for (int j = , len = pr[a[i]].size(); j < len; ++j)
{
int x = pr[a[i]][j];
fac[x].clear();
}
}
}
}
最大流:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e4 + ;
const int INF = 0x3f3f3f3f; int n, m; struct Edge {
int from;
int to;
int cap;
int flow;
inline Edge(){}
inline Edge(int from, int to, int cap, int flow) :from(from), to(to), cap(cap), flow(flow) {};
}; map<pair<int, int>, bool>mp;
vector<int>pre[];
vector<int>vec[];
int arr[maxn];
int sex[maxn];
vector<Edge>edge;
vector<int>G[maxn];
int vis[maxn];
int d[maxn];
int cur[maxn];
int S, T; inline void init()
{
mp.clear();
edge.clear();
for (int i = ; i <= n + ; ++i)
{
G[i].clear();
}
} inline void addedge(int from, int to, int cap)
{
edge.push_back(Edge(from, to, cap, ));
edge.push_back(Edge(to, from, , ));
int len = edge.size();
G[from].push_back(len - );
G[to].push_back(len - );
} inline bool BFS()
{
memset(d, , sizeof d);
memset(vis, , sizeof vis);
queue<int>q;
q.push(S);
d[S] = ;
vis[S] = ;
while (!q.empty())
{
int x = q.front();
q.pop();
for (auto it : G[x])
{
Edge &e = edge[it];
if (!vis[e.to] && e.cap > e.flow)
{
vis[e.to]
= ;
d[e.to] = d[x] + ;
q.push(e.to);
}
}
}
return vis[T];
} inline int DFS(int x, int a)
{
if (x == T || a == ) return a;
int flow = ;
int f = ;
for (int &i = cur[x]; i < G[x].size(); ++i)
{
Edge &e = edge[G[x][i]];
if (d[x] + == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > )
{
e.flow += f;
edge[G[x][i] ^ ].flow-f;
flow += f;
a -= f;
if (a == ) break;
}
}
return flow;
} inline int dicnic()
{
int ans = ;
while (BFS())
{
memset(cur, , sizeof cur);
ans += DFS(S, INF);
}
return ans;
} inline void work()
{
for (int i = ; i <= ; ++i)
{
if (pre[i].size() == )
{
for (int j = i; j <= ; j += i)
{
pre[j].push_back(i);
}
}
}
} int main()
{
work();
int t;
scanf("%d", &t);
while (t--)
{
init();
scanf("%d", &n);
S = , T = n + ;
for (int i = ; i <= n; ++i)
{
scanf("%d", &arr[i]);
}
for (int i = ; i <= n; ++i)
{
char c;
scanf(" %c", &c);
if (c == 'F')
{
for (auto it : pre[arr[i]])
{
vec[it].push_back(i);
}
sex[i] = ;
}
else
{
sex[i] = ;
}
}
for (int i = ; i <= n; ++i)
{
if (sex[i] == )
{
for (auto j : pre[arr[i]])
{
for (auto k : vec[j])
{
if (mp[make_pair(i, k)] == false)
{
addedge(i, k, );
mp[make_pair(i, k)] = mp[make_pair(k, i)] = true;
}
}
}
}
}
for (int i = ; i <= n; ++i)
{
if (sex[i] == ) addedge(, i, );
else if (sex[i] == ) addedge(i, n + , );
}
int ans = n - dicnic();
printf("%d\n", ans);
for (int i = ; i <= n + ; ++i)
{
for (auto x : pre[arr[i]])
{
vec[x].clear();
}
}
}
return ;
}
C:Intersections
题意:给出两个数组,数组里面是相同的数,然后相同的数之间连边,求有多少交点,交点重叠算多个点
思路:从第二个数组开始下手,考虑到当前位置,连边,如果之前的边连的点在当前点连的目标点的后面,就会产生一个点,也就是说统计一下之前有多少个点的目标点在目前这个点的目标点后面,树状数组处理一下
#include <bits/stdc++.h> using namespace std; #define N 100010
#define ll long long int t, n; int a[N], b[N];
int id[N]; int arr[N]; inline int lowbit(int x)
{
return x & (-x);
} inline void update(int x, int val)
{
for (int i = x; i <= n; i += lowbit(i))
arr[i] += val;
} inline int sum(int x)
{
int ans = ;
for (int i = x; i; i -= lowbit(i))
ans += arr[i];
return ans;
} int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = ; i <= n; ++i)
scanf("%d", a + i), id[a[i]] = i;
for (int i = ; i <= n; ++i)
scanf("%d", b + i);
memset(arr, , sizeof arr);
ll ans = ;
for (int i = ; i <= n; ++i)
{
int index = id[b[i]];
ans += sum(n) - sum(index);
update(index, );
}
printf("%lld\n", ans);
}
return ;
}
D:Balloons
水。
#include <bits/stdc++.h> using namespace std; int t, n; int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
int cnt = ;
for (int i = , num; i <= n; ++i)
{
scanf("%d", &num);
if (num == ) cnt ++;
}
printf("%d\n", n - cnt);
}
return ;
}
E:Maximum Sum
题意:在矩阵中选取部分数,使得权值最大,其中选中的数八个方向的数均不可在选取。、
思路:注意到n很小,可以考虑二进制位表示这个数取不取以及搜索的方法来写。其中遍历每个数的时候,决定这个数能否选取主要取决于这个数的左上角,上方,右上角,左方的数字是否选取。通过一个长度为(1 << 17)的数字表示当前这个数字的左上方到左方的状态。其中第低位表示当前数字的左上方,最高位表示当前数字的左方。在搜索中每个数都有两种状态,取和不取。每次都将当前状态右移一味,去掉没有影响的数字,在添上自己的状态,从而进行下一层的搜索。注意考虑当前数字在这一行第一位和最后一位的情况。最后再添加一点剪枝。
#include<bits/stdc++.h> using namespace std; int n;
int ans; int arr[][]; int type[][][ << ]; inline int DFS(int x, int y, int state)
{
if (x == n - && y == n) return ;
if (y == n) return DFS(x + , , state);
if (type[x][y][state] != -) return type[x][y][state];
//not
int res = DFS(x, y + , (state >> ));
//do
if (y == )
{
if (!(state & ( << )) && !(state & ( << ))) res = max(res, DFS(x, y + , ((state >> ) | ( << n))) + arr[x][y]);
}
else if (y == n - )
{
if (!(state & ) && !(state & ( << )) && !(state & ( << n))) res = max(res, DFS(x, y + , ((state >> ) | ( << n))) + arr[x][y]);
}
else
{
if (!(state & ) && !(state & ( << )) && !(state & ( << )) && !(state & ( << n))) res = max(res, DFS(x, y + , ((state >> ) | ( << n))) + arr[x][y]);
}
type[x][y][state] = res;
return res;
} int main()
{
int t;
scanf("%d", &t);
while (t--)
{
memset(type, -, sizeof type);
scanf("%d", &n);
for (int i = ; i < n; ++i)
for (int j = ; j < n; ++j)
scanf("%d", &arr[i][j]);
printf("%d\n", DFS(, , ));
}
return ;
}
F:Working Time
水。
#include <bits/stdc++.h> using namespace std; int t, n, m; int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &m);
int tot = ;
int a, b, c, d;
for (int i = ; i <= n; ++i)
{
scanf("%2d:%2d", &a, &b);
scanf("%2d:%2d", &c, &d);
int aa = a * + b;
int bb = c * + d;
tot += abs(aa - bb);
}
puts(tot >= m * ? "YES" : "NO");
}
return ;
}
G:Hard Equation
留坑。
(拓展BSGS)
H:Cube
水。
#include <bits/stdc++.h> using namespace std; int t, a; int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &a);
int ans = a / ;
ans = sqrt(ans);
printf("%d\n", ans);
}
return ;
}
I:Circles
题意:给出圆心,半径,求图中阴影部分面积
思路:四个小圆面积 + 大圆面积 - 矩形面积
#include <bits/stdc++.h> using namespace std; #define ll long long int t;
ll a, b, d; int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%lld%lld%lld", &a, &b, &d);
printf("%.10f\n", (d * d) * 1.0 / );
}
return ;
}
J: Smallest Difference
水。
#include<bits/stdc++.h>
using namespace std; #define N 10010 int arr[N]; int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(arr, ,sizeof arr);
int n;
scanf("%d",&n);
for(int i =;i<=n;++i)
{
int x;
scanf("%d",&x);
arr[x]++;
}
int ans = ;
for(int i = ;i <= ; ++i)
{
ans = max(arr[i] + arr[i + ], ans);
}
printf("%d\n",ans);
}
return ;
}
K:Citations
按题意模拟即可
#include <bits/stdc++.h> using namespace std; int t, n; string s; string author, title, journal, volume, number, pages, year; inline void Init()
{
author.clear();
title.clear();
journal.clear();
volume.clear();
number.clear();
pages.clear();
year.clear();
} inline void work(string &ans)
{
bool flag = false;
for (int i = , len = s.size(); i < len; ++i)
{
if (s[i] == '{')
{
flag = true;
continue;
}
if (s[i] == '}') return;
if (flag == false) continue;
ans += s[i];
}
return;
} inline bool Find(string t)
{
if (t.size() > s.size()) return false;
for (int i = , len = t.size(); i < len; ++i)
{
if (s[i] != t[i]) return false;
}
return true;
} inline void work_author()
{
bool flag = false;
bool fi = false;
int cnt = ;
for (int i = , len = s.size(); i < len; ++i)
{
if (s[i] == '{')
{
flag = true;
continue;
}
if (s[i] == '}') return;
if (isalpha(s[i]) && flag)
{
if (fi == false)
{
if(cnt) author += ", ";
author += s[i];i++;
author += s[i];
author += ". ";
while (s[i] != ' ') i++;
fi = true;
}
else
{
author += s[i];
while (s[i] != ',') i++;
cnt++;
fi = false;
}
}
}
} int main()
{
cin.tie();
cout.tie();
ios::sync_with_stdio(false);
cin >> t;
while (t--)
{
cin >> n;
while (n--)
{
Init();
getline(cin, s);
while (getline(cin, s))
{
if (s == "}") break;
if (Find("author")) work_author();
else if (Find("title")) work(title);
else if (Find("journal")) work(journal);
else if (Find("volume")) work(volume);
else if (Find("number")) work(number);
else if (Find("year")) work(year);
else if (Find("pages")) work(pages);
else continue;
}
cout << author << ". " << title << ". " << journal << ". " << year << ";" << volume << "(" << number << "):" << pages << ".\n";
}
}
}
赛后总结:
- 考虑数据中是否有特殊点会影响答案
- 模拟题请考虑更多细节
- 很多东西可以多考虑一点,比如给出的两个数,按题意是需要有大小关系,但是数据不一定保证其大小关系
ACM ICPC, JUST Collegiate Programming Contest (2018) Solution的更多相关文章
- ACM ICPC, Amman Collegiate Programming Contest (2018) Solution
Solution A:Careful Thief 题意:给出n个区间,每个区间的每个位置的权值都是v,然后找长度为k的区间,使得这个区间的所有位置的权值加起来最大,输出最大权值, 所有区间不重叠 思路 ...
- ACM ICPC, Damascus University Collegiate Programming Contest(2018) Solution
A:Martadella Stikes Again 水. #include <bits/stdc++.h> using namespace std; #define ll long lon ...
- ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018
ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syr ...
- German Collegiate Programming Contest 2018 B. Battle Royale
Battle Royale games are the current trend in video games and Gamers Concealed Punching Circles (GCPC ...
- German Collegiate Programming Contest 2018 C. Coolest Ski Route
John loves winter. Every skiing season he goes heli-skiing with his friends. To do so, they rent a h ...
- ICPC — International Collegiate Programming Contest Asia Regional Contest, Yokohama, 2018–12–09 题解
目录 注意!!此题解存在大量假算法,请各位巨佬明辨! Problem A Digits Are Not Just Characters 题面 题意 思路 代码 Problem B Arithmetic ...
- [ACM International Collegiate Programming Contest, Amman Collegiate Programming Contest (2018)]
https://codeforces.com/gym/101810 A. Careful Thief time limit per test 2.5 s memory limit per test 2 ...
- 2019.04.04 第二次训练 【ACM International Collegiate Programming Contest, JUST Collegiate Programming Contest (2018)】
题目链接:https://codeforces.com/gym/101853 A: ✅ B: (二分图匹配) https://blog.csdn.net/qq_41997978/article/det ...
- Gym - 101810H ACM International Collegiate Programming Contest (2018)
bryce1010模板 http://codeforces.com/gym/101810 #include <bits/stdc++.h> using namespace std; #de ...
随机推荐
- NodeJS-001-Nodejs学习文档整理(转-出自http://www.cnblogs.com/xucheng)
Nodejs学习文档整理 http://www.cnblogs.com/xucheng/p/3988835.html 1.nodejs是什么: nodejs是一个是javascript能在后台运行的平 ...
- [转载]SQL truncate 、delete与drop区别
相同点: 1.truncate和不带where子句的delete.以及drop都会删除表内的数据. 2.drop.truncate都是DDL语句(数据定义语言),执行后会自动提交. 不同点: 1. t ...
- /etc/hosts
/etc/hosts 是 Linux 系统中一个负责IP地址与域名快速解析的文件,解析优先级:DNS缓存 > hosts > DNS服务(/etc/resolv.conf) 文件格式:网络 ...
- C语言各种存储模式的区别?最常用的存储模式有哪些?
DOS用一种段地址结构来编址计算机的内存,每一个物理内存位置都有一个可通过段地址一偏移量的方式来访问的相关地址.为了支持这种段地址结构,大多数C编译程序都允许你用以下6种存储模式来创建程序: ---- ...
- 格式化输出%s和%S的区别
使用s时,printf是针对单字节字符的字符串,而wprintf是针对宽字符的 使用S时,正好相反,printf针对宽字符 CString中的format与printf类似,在unicode字符集的工 ...
- Js跨域、父级窗口执行JS赋值、取值,更改元素
网站域名: A:http://www.xxoo.com/a.html B:http://www.aabb.com/b.html B网站嵌套与A网站(A的a中的Iframe指向B中的b)b要让父级a页面 ...
- 静态同步synchronized方法和synchronized(class)代码块
关键字synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类进行持锁. package synStaticMethod; /** * C ...
- 【BZOJ2938】[Poi2000]病毒 AC自动机+DFS
[BZOJ2938][Poi2000]病毒 Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码 ...
- iOS CoreMotion 纪录步数
- (void)startUpdateAccelerometer{ /* 设置采样的频率,单位是秒 */ NSTimeInterval updateInterval = 0.05; // ...
- 从零搭建 vue-cli 脚手架
前言: 用了几次 vue-cli 做 vue 项目,感觉没什么大问题,虽然也没有用 vue-router 和 vuex .但是心里一直有个梗,就是最初的目录生成和配置文件,一直没动过,也不知道具体原理 ...