2018-2019 Russia Open High School Programming Contest
A. Company Merging
Solved.
温暖的签到。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + ;
typedef long long ll;
struct node{
int val, num;
node(){}
node(int val, int num):val(val), num(num){}
}arr[maxn];
int n, m;
int main()
{
while(~scanf("%d", &n))
{
int Max = ;
for(int i = ; i <= n; ++i)
{
scanf("%d", &arr[i].num);
arr[i].val = ;
for(int j = , x; j <= arr[i].num; ++j)
{
scanf("%d", &x);
arr[i].val = max(arr[i].val, x);
}
Max = max(arr[i].val, Max);
}
ll ans = ;
for(int i = ; i <= n; ++i)
{
// cout << arr[i].val << " " << endl;
ans += 1ll * arr[i].num * (Max - arr[i].val);
}
printf("%lld\n", ans);
}
return ;
}
B. LaTeX Expert
Solved.
按题意模拟即可。
#include <bits/stdc++.h>
using namespace std; #define N 100010
string str, s;
string st = "\\begin{thebibliography}{99}";
string ed = "\\end{thebibliography}";
map <string, int> mp;
int cnt, now; bool same;
string res[N]; int getid(string s)
{
if (mp.find(s) == mp.end()) mp[s] = ++cnt;
return mp[s];
} void work()
{
int len = str.size();
string tmp = ""; bool add = ;
for (int i = ; i < len; ++i)
{
if (str[i] == '{') add = ;
else if (str[i] == '}')
{
getid(tmp);
tmp = "";
add = ;
}
else if (add) tmp += str[i];
}
} void add()
{
int len = s.size();
string tmp = ""; bool add = ;
for (int i = ; i < len; ++i)
{
if (s[i] == '{') add = ;
else if (s[i] == '}')
{
++now;
int id = getid(tmp);
if (id != now) same = false;
res[id] = s;
return;
}
else if (add)
tmp += s[i];
}
} int main()
{
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
cnt = ; now = ;
bool start = ;
same = true;
str = "";
while (getline(cin, s))
{
if (s == "") continue;
if (s == st)
{
start = ;
work();
continue;
}
if (s == ed)
{
if (same)
{
cout << "Correct\n";
return ;
}
cout << "Incorrect\n";
cout << st << "\n";
for (int i = ; i <= cnt; ++i)
cout << res[i] << "\n";
cout << ed << "\n";
}
if (start)
add();
else
str += s;
}
return ;
}
C. New Year Presents
Upsolved.
题意:
有$n$个小朋友,每个小朋友有$s_i$件不同的物品,一个小朋友可以将自己的一件物品给另一个小朋友,前提是另一个小朋友没有这件物品,这样记为一次转移
求最少的转移次数使得拥有最多数量物品的小朋友和拥有最少数量物品的小朋友他们拥有的物品数量差值不超过1.
思路:
首先拥有东西多的小朋友肯定能往拥有东西少的小朋友转移(根据鸽笼原理),那只要把物品多的小朋友放在一起,然后去转移给物品少的小朋友就好了
注意枚举的技巧,复杂度应该跟$O(n)有关?$
#include <bits/stdc++.h>
using namespace std; #define N 100010
struct node
{
int l, r, x;
node () {}
node (int l, int r, int x) : l(l), r(r), x(x) {}
};
vector <int> vec[N];
int n, m;
int vis[N];
vector <node> res;
int a[N * ], now[N], nx[N * ], last;
int sze[N];
queue <int> q; void add(int x, int id)
{
a[++last] = x;
nx[last] = now[id];
now[id] = last;
} int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
int tot = ;
res.clear();
memset(now, , sizeof now);
for (int i = , x, y; i <= n; ++i)
{
scanf("%d", &x);
tot += x;
vec[i].clear();
for (int j = ; j <= x; ++j)
{
scanf("%d", &y);
vec[i].push_back(y);
}
sze[i] = vec[i].size();
}
if (tot % n == )
{
int x = tot / n;
for (int i = ; i <= n; ++i)
if (sze[i] > x)
for (auto it : vec[i])
add(i, it);
for (int i = ; i <= m; ++i)
if (now[i]) q.push(i);
for (int i = , front; i <= n; ++i)
if (sze[i] < x)
{
for (auto it : vec[i])
vis[it] = ;
while (sze[i] < x)
{
front = q.front(); q.pop();
//printf("%d %d %d\n", i, sze[i], front);
if (vis[front])
{
q.push(front);
continue;
}
int id = now[front];
for (; id ; id = nx[id])
{
if (sze[a[id]] <= x) continue;
res.push_back(node(a[id], i, front));
vec[i].push_back(front);
vis[front] = ;
--sze[a[id]];
++sze[i];
id = nx[id];
break;
}
if (id) q.push(front);
now[front] = id;
}
for (auto it : vec[i])
vis[it] = ;
}
}
else
{
int x = tot / n + ;
int need = n - tot % n;
for (int i = ; i <= n; ++i)
if (sze[i] > x)
for (auto it : vec[i])
add(i, it);
for (int i = ; i <= m; ++i)
if (now[i]) q.push(i);
for (int i = , front; i <= n; ++i)
if (sze[i] < x)
{
if (sze[i] == x - && need)
{
--need;
continue;
}
for (auto it : vec[i])
vis[it] = ;
while (sze[i] < x)
{
if (sze[i] == x - && need)
{
--need;
break;
}
front = q.front(); q.pop();
if (vis[front])
{
q.push(front);
continue;
}
int id = now[front];
for (; id; id = nx[id])
{
if (sze[a[id]] <= x) continue;
res.push_back(node(a[id], i, front));
vec[i].push_back(front);
vis[front] = ;
--sze[a[id]];
++sze[i];
id = nx[id];
break;
}
if (id) q.push(front);
now[front] = id;
}
for (auto it : vec[i])
vis[it] = ;
}
}
int len = res.size();
printf("%d\n", len);
for (int i = ; i < len; ++i)
printf("%d %d %d\n", res[i].l, res[i].r, res[i].x);
}
return ;
}
D. Similar Arrays
Solved.
找到一组没有任何关系的$i, j$填上1/1, 1/2, 其他的分别填入3-n。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + ; int n, m;
set<int>s[maxn];
int arr[maxn], brr[maxn]; void solve()
{
for(int i = ; i <= n; ++i)
{
for(int j = i + ; j <= n; ++j) if(s[i].count(j) == )
{
arr[i] = , arr[j] = ;
brr[i] = , brr[j] = ;
int pos = ;
for(int k = ; k <= n; ++k)if(!arr[k])
{
arr[k] = brr[k] = pos++;
}
puts("YES");
for(int k = ; k <= n; ++k) printf("%d%c", arr[k], " \n"[k == n]);
for(int k = ; k <= n; ++k) printf("%d%c", brr[k], " \n"[k == n]);
return ;
}
}
puts("NO");
} int main()
{
while(~scanf("%d %d", &n, &m))
{
for(int i = ; i <= n; ++i) s[i].clear(), arr[i] = brr[i] = ;
for(int i = , l, r; i <= m; ++i)
{
scanf("%d %d", &l, &r);
s[min(l, r)].insert(max(l, r));
}
solve();
}
return ;
}
E. Horseback Riding
Solved.
枚举每个终点, 跑一边$BFS$, 暴力搜索, 记录状态。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e2 + ; int n;
vector<pair<int, int> >ans;
char str[maxn];
int vis[maxn];
int dis[maxn];
int pre[maxn];
int dir[][] = {, , , -, -, , -, -, , , , -, -, , -, -}; bool judge(int x, int y)
{
if(x < || x >= || y < || y >= || dis[x * + y]) return false;
else return true;
} void BFS(int st)
{
memset(dis, , sizeof dis);
memset(pre, -, sizeof pre);
queue<int>q;
q.push(st);
dis[st] = ;
while(!q.empty())
{
int x = q.front() / ;
int y = q.front() % ;
q.pop();
for(int j = ; j < ; ++j)
{
int dx = x + dir[j][];
int dy = y + dir[j][];
if(judge(dx, dy))
{
dis[dx * + dy] = dis[x * + y] + ;
pre[dx * + dy] = x * + y;
q.push(dx * + dy);
}
}
}
} int main()
{
while(~scanf("%d", &n))
{
memset(vis, , sizeof vis);
ans.clear();
for(int i = ; i <= n; ++i)
{
scanf("%s", str);
vis[(str[] - '') * + str[] - 'a'] = ;
}
ans.clear();
for(int i = ; i < n; ++i)
{
BFS(i);
int ed = i;
while(!vis[ed]) ++ed;
vis[ed] = ;
while(ed != i)
{
vector<int>path;
do{
path.push_back(ed);
ed = pre[ed];
}while(vis[ed]);
path.push_back(ed);
for(int j = path.size() - ; j >= ; --j) ans.push_back(make_pair(path[j - ], path[j]));
}
vis[ed] = ;
}
int len = ans.size();
printf("%d\n", len);
for(auto it : ans)
{
printf("%c%d-%c%d\n", it.first % + 'a', it.first / + , it.second % + 'a', it.second / + );
}
}
return ;
}
F. How to Learn You Score
Upsolved.
题意:
有$n$个数,每次可以询问三个数,返回这三个数的最大值+最小值的和,用不超过$4 \cdot n$次的询问求出这$n$个数是什么
思路:
考虑$4$个数的时候,一共有$4$种询问方式,将这四种询问方式得到的四个值取最大最小值加起来就是这四个值的和
那么五个数我们就得到任意四个数的和,我们令$sum_i$表示不包含第$i$个数的和
那么有
$a_i + sum_i = a_j + sum_j$
有
$a_1 + sum_1 = a_2 + sum_2 = a_3 + sum_3 = a_4 + sum_4 = a_5 + sum_5$
联立后有
$4 \cdot a_1 = \sum\nolimits_{i = 1}^{5} sum_i - 4 \cdot sum_1$
依次求出这五个数
然后考虑后面的数可以用前面已知的数通过四次询问推出
总的询问次数$4 \cdot n$
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 1010
int n;
ll a[N]; void work(int l, int r)
{
int ord[]; ll sum[];
for (int i = , j = l; i <= ; ++i, ++j)
ord[i] = j;
//for (int i = 1; i <= 5; ++i) printf("%d%c", ord[i], " \n"[i == 5]);
for (int i = ; i <= ; ++i)
{
vector <ll> vec;
int id[], id2[];
ll x;
for (int j = , k = ; j <= ; ++j)
if (i != j)
id[++k] = ord[j];
//for (int j = 1; j <= 4; ++j)
// printf("%d%c", id[j], " \n"[j == 4]);
for (int j = ; j <= ; ++j)
{
for (int k = , o = ; k <= ; ++k)
if (j != k)
id2[++o] = id[k];
printf("? ");
for (int k = ; k <= ; ++k)
printf("%d%c", id2[k], " \n"[k == ]);
fflush(stdout);
scanf("%lld", &x);
vec.push_back(x);
}
sort(vec.begin(), vec.end());
sum[i] = vec.end()[-] + *vec.begin();
}
//for (int i = 1; i <= 5; ++i)
// printf("%lld%c", sum[i], " \n"[i == 5]);
ll tot = ;
for (int i = ; i <= ; ++i)
tot += sum[i];
for (int i = ; i <= ; ++i)
{
//assert((4ll * sum[i] - tot) % 4 == 0);
a[l + i - ] = -(4ll * sum[i] - tot) / ;
}
} ll get(int l, int r)
{
int id[], id2[];
vector <ll> vec;
ll x;
for (int i = ; i <= ; ++i)
id[i] = i + l - ;
for (int j = ; j <= ; ++j)
{
for (int k = , o = ; k <= ; ++k)
if (j != k)
id2[++o] = id[k];
printf("? ");
for (int k = ; k <= ; ++k)
printf("%d%c", id2[k], " \n"[k == ]);
fflush(stdout);
scanf("%lld", &x);
vec.push_back(x);
}
sort(vec.begin(), vec.end());
return vec.end()[-] + *vec.begin();
} int main()
{
while (scanf("%d", &n) != EOF)
{
work(, );
for (int i = ; i <= n; ++i)
{
ll tot = get(i - , i);
for (int j = i - ; j < i; ++j)
tot -= a[j];
a[i] = tot;
}
printf("! ");
for (int i = ; i <= n; ++i)
printf("%lld%c", a[i], " \n"[i == n]);
fflush(stdout);
}
return ;
}
I. Minimal Product
Solved.
题意:求一个序列$找一个最小的a_i \cdot a_j 并且满足i < j, a_i < a_j$
思路:
正着扫一遍维护最小值,倒着扫一遍维护最大值。
注意生成序列的时候的取模,要自然溢出,否则会爆ll
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll MOD = 1ll << ;
const ll INFLL = 5e18;
const int maxn = 1e7 + ; ll n, l, r;
ll arr[maxn];
unsigned int x, y,z, b1, b2;
unsigned int brr[maxn]; int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%lld %lld %lld %u %u %u %u %u", &n, &l, &r, &x, &y, &z, &b1, &b2);
brr[] = b1;
brr[] = b2;
for(int i = ; i <= n; ++i) brr[i] = (brr[i - ] * x + brr[i - ] * y + z);
for(int i = ; i <= n; ++i) arr[i] = (brr[i] % (r - l + ) + l);
int flag = ;
ll ans = INFLL;
ll Max = -INFLL;
for(int i = n; i >= ; --i)
{
if(arr[i] < Max)
{
flag = ;
ans = min(ans, arr[i] * Max);
}
Max = max(Max, arr[i]);
}
ll Min = INFLL;
for(int i = ; i <= n; ++i)
{
if(arr[i] > Min)
{
flag = ;
ans = min(ans, arr[i] * Min);
}
Min = min(Min, arr[i]);
}
if(!flag) puts("IMPOSSIBLE");
else printf("%lld\n", ans);
}
return ;
}
K. Right Expansion Of The Mind
Solved.
分为s, t两个字符串讨论。
对于t字符串, 只要两个t字符串含有相同字母即可。
对于s字符串, 从后往前删除在t字符串中的字符, 知道找到一个不在t字符串中的字符, 那么另一个可以匹配的字符串, 前缀相同。
#include<bits/stdc++.h> using namespace std; int n;
string s, t;
map<pair<string, int>, vector<int> >mp; int main()
{
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
while(cin >> n)
{
mp.clear();
for(int i = ; i <= n; ++i)
{
cin >> s >> t;
int tmp = ;
for(int j = , len = t.length(); j < len; ++j) tmp |= ( << (t[j] - 'a'));
int len = s.length();
for(int j = len - ; j >= ; --j)
{
if(tmp & ( << (s[j] - 'a'))) s.erase(s.begin() + j);
else break;
}
mp[make_pair(s, tmp)].push_back(i);
}
int res = mp.size();
cout << res << "\n";
for(auto vec : mp)
{
int len = vec.second.size();
cout << len;
for(auto it : vec.second)
{
cout << " " << it;
}
cout << "\n";
}
}
return ;
}
L. erland University
Solved.
二分答案。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; ll t, n, a, b, k; bool check(ll mid)
{
ll res = mid * k;
ll tmp = min(a, mid) * (n / + n % ) + min(b, mid) * (n / );
return res <= tmp;
} int main()
{
while(~scanf("%lld %lld %lld %lld %lld", &t ,&n, &a, &b, &k))
{
ll l = , r = t, res = ;
while(r - l >= )
{
ll mid = (l + r) >> ;
if(check(mid))
{
l = mid + ;
res = mid;
}
else
{
r = mid - ;
}
}
printf("%lld\n", res);
}
return ;
}
M. The Pleasant Walk
Solved.
温暖的签到。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + ; int n, k;
int dp[maxn];
int arr[maxn]; int main()
{
while(~scanf("%d %d", &n, &k))
{
int ans = ;
memset(dp, , sizeof dp);
for(int i = ; i <= n; ++i) scanf("%d", arr + i);
for(int i = ; i <= n; ++i)
{
dp[i] = ;
if(arr[i] != arr[i - ]) dp[i] = max(dp[i - ] + , dp[i]);
ans = max(ans, dp[i]);
}
printf("%d\n", ans);
}
return ;
}
2018-2019 Russia Open High School Programming Contest的更多相关文章
- Codeforces 1090A - Company Merging - [签到水题][2018-2019 Russia Open High School Programming Contest Problem A]
题目链接:https://codeforces.com/contest/1090/problem/A A conglomerate consists of n companies. To make m ...
- Codeforces 1090B - LaTeX Expert - [字符串模拟][2018-2019 Russia Open High School Programming Contest Problem B]
题目链接:https://codeforces.com/contest/1090/problem/B Examplesstandard input The most famous characters ...
- Codeforces 1090D - Similar Arrays - [思维题][构造题][2018-2019 Russia Open High School Programming Contest Problem D]
题目链接:https://codeforces.com/contest/1090/problem/D Vasya had an array of n integers, each element of ...
- Codeforces 1090M - The Pleasant Walk - [签到水题][2018-2019 Russia Open High School Programming Contest Problem M]
题目链接:https://codeforces.com/contest/1090/problem/M There are n houses along the road where Anya live ...
- 计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛
Tree Ming and Hong are playing a simple game called nim game. They have nn piles of stones numbered ...
- CF_2018-2019 Russia Open High School Programming Contest (Unrated, Online Mirror, ICPC Rules, Teams Preferred)
只做了两个就去上课去啦... A. Company Merging time limit per test 1 second memory limit per test 512 megabytes i ...
- 2019 The 19th Zhejiang University Programming Contest
感想: 今天三个人的状态比昨天计院校赛的状态要好很多,然而三个人都慢热体质导致签到题wa了很多发.最后虽然跟大家题数一样(6题),然而输在罚时. 只能说,水题还是刷得少,看到签到都没灵感实在不应该. ...
- 2018-2019 Russia Open High School Programming Contest (Unrated, Online Mirror, ICPC Rules, Teams Preferred)
前言 有一场下午的cf,很滋磁啊,然后又和dalao(见右面链接)组队打了,dalao直接带飞我啊. 这是一篇题解,也是一篇总结,当然,让我把所有的题目都写个题解是不可能的了. 按照开题顺序讲吧. 在 ...
- C.0689-The 2019 ICPC China Shaanxi Provincial Programming Contest
We call a string as a 0689-string if this string only consists of digits '0', '6', '8' and '9'. Give ...
随机推荐
- PL/SQL编程1-基础
编写第一个存储过程 create or replace procedure test_pro1 is begin ','zydev'); end; / 查看错误 show error 执行存储过程 e ...
- 当div没有设置宽度,使用width的fit-content和margin:auto实现元素的水平居中
当我们做水平居中的时候,会有许多方法,margin:0 auto,或者test-align:center,以及flex布局.当元素的width不固定的时候,我们如何实现水平居中呢,代码如下: < ...
- c++11——lambda表达式
lambda表达式 函数式编程的一个语法,有如下优点: (1)声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象.以更直接的方式写程序,好的可读性和可维护性. (2) ...
- springdata----->spring集成redis(一)
使用spring-data-redis与redis集成,今天我们就通过例子来学习一下.当时间和耐心都已经变为奢侈,我们只能靠星座了解彼此. spring与redis集成的实例 注意:这里我们测试的是安 ...
- 静态同步synchronized方法和synchronized(class)代码块
关键字synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类进行持锁. package synStaticMethod; /** * C ...
- 封装JDBC工具类
JDBC连接数据库基本的步骤是固定的,这样就可以考虑封装一个工具类来简化数据库操作. 封装时用到了Java中的properties配置文件,是以一种键值对的形式存在的,可以把连接数据库要动态的信息保存 ...
- 去面试H5游戏问的一些问题
首先肯定是自我介绍,然后问一些基础题,然后问简历上的相关问题. 1. WebSocket和Socket的区别 2.Http和Https的区别,get和post区别 3.进程和线程 4.H5的渲染流程 ...
- 【BZOJ3772】精神污染 DFS序+主席树
[BZOJ3772]精神污染 Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是 ...
- Unity3D 笔记二 3D模型基础
一.3D模型基础 1.Hierarchy 显示的是界面上的游戏对象(GameObject),每个游戏对象都有.至少要有一个Camera,点击Camera就可以在Preview中看到摄像机的视角画面.每 ...
- 基于Token的身份验证--JWT
初次了解JWT,很基础,高手勿喷. 基于Token的身份验证用来替代传统的cookie+session身份验证方法中的session. JWT是啥? JWT就是一个字符串,经过加密处理与校验处理的字符 ...