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 ...
随机推荐
- remove()
remove() 用于从列表中删除指定的元素 In [35]: l = ['a', 'b', 'c'] In [36]: l.remove('b') In [37]: l Out[37]: ['a', ...
- Python 转义字符
转义字符 说明 \ 用在一行的末尾,表示续行符 \r 回车 \n 换行符 \\ 打印反斜杠 \' 打印单引号 \" 打 ...
- 在create-react-app的脚手架里面使用scss
之前用vue-cli脚手架的时候,只需要引进sass需要的依赖包便可以引入scss,但是在create-react-app的时候,发现除了需要引入sass依赖,还需要进行配置: 不管用什么方法进行sa ...
- centos 7 搭建ntp 服务器
第一步 安装ntp yum install ntp 第二步,查找最近的时间同步服务器 http://www.pool.ntp.org/zone/asia 第三部编辑 /etc/ntp.conf ser ...
- MQTT的学习研究(三)moquette-mqtt 的使用之mqtt服务发布主题信息
接着上一篇的moquette-mqtt 的使用之broker启动之后,我们需要启动moquette-mqtt 的服务端发布消息. 在moquette-mqtt 的mqtt-client中三种方式实现发 ...
- synchronized同步方法
“非线程安全”其实会在多个线程对同一个对象中的实例变量进行并发访问的时候产生,产生的后果是脏读,也就是取到的数据是被更改过的.而“线程安全”就是以获得的实例变量的值是经过同步处理的,不会出现脏读的现象 ...
- Java中UDP协议的基本原理和简单用法
UDP协议是非面向连接的,相对于TCP协议效率较高,但是不安全.UDP协议类似发信息的过程,不管接收方是在线还是关机状态,都会把信息发送出去.但是如果接收方不处于接收信息的状态,发送出去的数据包就会丢 ...
- Ubuntu16.04安装Elasticsearch
一.安装工作 wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - sudo apt-g ...
- css 分栏高度自动相等
方法2: <div class="ticket_table"> <div class="ticket_l"> <h3>全票& ...
- 【Android】Android实现自定义带文字和图片的Button
在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就是利用系统自带的Button来实现,这种方式代码量最 ...