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 ...
随机推荐
- 查看磁盘读写:iotop
iotop命令用来动态地查看磁盘IO情况,用法如下: [root@localhost ~]$ yum install -y iotop # 安装iotop命令 [root@localhost ~]$ ...
- PHP webservice 接口实例
原文地址,就不摘抄了 http://www.sky00.com/archives/91.html
- APP适配IOS8,iPhone6和Plus截图简要说明
本文转载至 http://blog.csdn.net/yongyinmg/article/details/41422873 原文:http://www.zcool.com.cn/article/ZMT ...
- 《C++ Primer Plus》第9章 内存模型和名称空间 学习笔记
C++鼓励程序员在开发程序时使用多个文件.一种有效的组织策略是,使用头文件来定义用户类型,为操纵用户类型的函数提供函数原型,并将函数定义放在一个独立的源代码文件中.头文件和源代码文件一起定义和实现了用 ...
- cocos2dx游戏--欢欢英雄传说--添加触摸响应
主要的调整就是将HelloWorldScene改成了MainSecne,然后将Player作为了MainScene的私有成员变量来处理.修改了人物图片,使用了网上找到的三国战纪的人物素材代替我之前画的 ...
- 《转》python学习(5)--数据类型
转自 http://www.cnblogs.com/BeginMan/archive/2013/06/08/3125876.html 一.标准类型函数 cmp():比较大小 str():转换为字符串 ...
- ubuntu 14 root 账户 启用与ssh登录
ubuntu 14.04 root用户登录 开启root帐号的方法: 为了启用root 帐号(也就是设置一个口令)使用: sudo passwd root 当你使用完毕后屏蔽root帐号使用: sud ...
- MyBatis——Java API
Java API 既然你已经知道如何配置 MyBatis 和创建映射文件,你就已经准备好来提升技能了. MyBatis 的 Java API 就是你收获你所做的努力的地方.正如你即将看到的,和 JDB ...
- sencha touch 入门系列 (七)sencha touch 类系统讲解(上)
在mvc结构的基础上,sencha touch又使用了sencha公司为extjs4开发出来的类系统,在面向对象的编程语言中,类是对对象的定义,它描述了对象所包含的大量属性和方法. 跟面向对象语言类似 ...
- RabbitMQ的安装和使用Python连接RabbitMQ
绪论 这里的环境使用的是Mac OS X系统,所有的配置和使用都是基于Mac OS X 和Python 2.7 以及对应的pika库的. RabbitMQ的安装和配置 安装部分 #brew insta ...