Educational Codeforces Round 59 Solution
A. Digits Sequence Dividing
签.
#include <bits/stdc++.h>
using namespace std; #define N 1010
char s[N]; int n; void solve()
{
if (n == && s[] >= s[])
{
puts("NO");
return;
}
else
{
puts("YES");
puts("");
printf("%c %s\n", s[], s + );
}
} int main()
{
int t; scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
scanf("%s", s + );
solve();
}
return ;
}
B. Digital root
签.
#include <bits/stdc++.h>
using namespace std; #define ll long long
int t;
ll k, x; int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%lld%lld", &k, &x);
printf("%lld\n", (k - ) * + x);
}
return ;
}
C. Brutality
每次连续的一段中如果大于$k个,取最大的k个$
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 200010
int n, k;
ll a[N];
char s[N]; int main()
{
while (scanf("%d%d", &n, &k) != EOF)
{
for (int i = ; i <= n; ++i) scanf("%lld", a + i);
scanf("%s", s + ); s[n + ] = '#';
priority_queue <ll> pq; pq.push(a[]);
ll res = ;
for (int i = ; i <= n + ; ++i)
{
if (s[i] != s[i - ])
{
for (int j = k; !pq.empty() && j; --j)
{
res += pq.top(); pq.pop();
}
while (!pq.empty()) pq.pop();
}
pq.push(a[i]);
}
printf("%lld\n", res);
}
return ;
}
D. Compression
Solved.
题意:
有$n \cdot n的01矩阵,把矩阵压缩,压缩后的大小为\frac {n}{x}$
思路:
考虑$x | n, 枚举n的因数,在5200范围下,最多有60个$
$然后每次枚举因数n^2判断是否可以 就可以喜提TLE一枚$
$我们考虑用bitset优化$
$我们先处理出b数组第一行,然后接下来x - 1行都可以直接位运算赋值$
$那么这个复杂度就是O(\frac{n^2}{64} + (\frac{n^2}{x}))$
我们发现$< x 的因数不会太多 当因数 > x 的时候 复杂度就接近O(\frac{n^2}{64})$
$然后和a数字异或可以O(\frac{n^2}{64}) 判断合法性$
#include <bits/stdc++.h>
using namespace std; #define N 5510
int n;
bitset <N> a[N], b[N], tmp;
char s[N][N];
char Hash[];
int res; void change(int x)
{
a[x].reset();
for (int i = , j = ; i <= n / ; ++i)
{
int num = Hash[s[x][i]];
for (int k = ; k >= ; --k)
a[x][++j] = (num >> k) & ;
}
} bool solve(int x)
{
for (int i = ; i <= n; i += x)
{
tmp.reset();
for (int j = ; j <= n; j += x)
for (int k = j; k < j + x; ++k)
tmp[k] = a[i][j];
for (int j = i; j < i + x; ++j)
{
b[j] &= ;
b[j] |= tmp;
}
}
for (int i = ; i <= n; ++i) if ((a[i] ^ b[i]) != )
{
return false;
}
return true;
} int main()
{
for (int i = ; i <= ; ++i) Hash[i + ''] = i;
Hash['A'] = ;
Hash['B'] = ;
Hash['C'] = ;
Hash['D'] = ;
Hash['E'] = ;
Hash['F'] = ;
while (scanf("%d", &n) != EOF)
{
for (int i = ; i <= n; ++i)
scanf("%s", s[i] + );
for (int i = ; i <= n; ++i) change(i);
res = ;
vector <int> fac;
for (int i = ; i * i <= n; ++i) if (n % i == ) fac.push_back(i), fac.push_back(n / i);
sort(fac.begin(), fac.end());
fac.erase(unique(fac.begin(), fac.end()), fac.end());
reverse(fac.begin(), fac.end());
for (auto it : fac) if (it > )
{
if (solve(it))
{
res = it;
break;
}
}
printf("%d\n", res);
}
return ;
}
E. Vasya and Binary String
Upsolved.
题意:
有一个01串,每次可以取连续的一段相同的消除
消除后剩下的两段合并,给出连续消去$x个可以获得的价值$
求最大价值
思路:
$dp[l][r][k]表示区间[l, r]并且末尾接着k个与r相同的字符的最大价值$
$那么转移可以在[l, r]中找一个i使得s[i] = s[r] 那么答案就是 dp[l][i][k + 1] + dp[i + 1][r - 1][0]$
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 110 int n;
char s[N];
ll a[N];
ll dp[N][N][N]; ll DFS(int l, int r, int k)
{
if (r < l) return ;
if (l == r) return a[k + ];
if (dp[l][r][k] != -) return dp[l][r][k];
dp[l][r][k] = a[k + ] + DFS(l, r - , );
for (int i = l; i < r; ++i) if (s[i] == s[r])
dp[l][r][k] = max(dp[l][r][k], DFS(l, i, k + ) + DFS(i + , r - , ));
return dp[l][r][k];
} int main()
{
while (scanf("%d", &n) != EOF)
{
scanf("%s", s + );
for (int i = ; i <= n; ++i) scanf("%lld", a + i);
memset(dp, -, sizeof dp);
printf("%lld\n", DFS(, n, ));
}
return ;
}
F. Vasya and Endless Credits
Upsolved.
题意:
有一个人可以向银行借款
$a_i, b_i, k_i$
$a_i表示借a_i元,b_i表示在接下来的k_i个月需要给银行b_i元钱$
求如何借款,使得其中某个月拥有最大的钱数
思路:
$dp[i]表示一共借款i个月的最大价值$
$假如我们有一个方案,那么这个方案得到的a_i的总和一样的情况下$
$我们希望将b_i大的借的月数较少,这样得到的钱数更多$
$可以先将b_i排序,再dp$
$每次可以将dp[i + 1] + dp[i] + 当前物品借i个月的价值$
$或者dp[i] 可以直接更新为加上当前月借满的状态$
$这样转移的时候就不用讨论i和k的大小关系$
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 510
int n;
struct node
{
ll a, b, k;
void scan() { scanf("%lld%lld%lld", &a, &b, &k); }
bool operator < (const node &other) const { return b > other.b; }
}a[N];
ll dp[N]; int main()
{
while (scanf("%d", &n) != EOF)
{
for (int i = ; i <= n; ++i) a[i].scan();
sort(a + , a + + n);
memset(dp, , sizeof dp);
for (int i = ; i <= n; ++i)
{
for (int j = n - ; j >= ; --j)
{
dp[j + ] = max(dp[j + ], dp[j] + a[i].a - a[i].b * j);
dp[j] = max(dp[j], dp[j] + a[i].a - a[i].b * a[i].k);
}
}
printf("%lld\n", *max_element(dp, dp + + n));
}
return ;
}
G. Vasya and Maximum Profit
Upsolved.
题意:
有一些题目,可以选择连续的一段卖出去
设题目数为$x,则得到的利润为 a \cdot x - \sum c_i - max(d[i + 1] - d[i])^2$
思路:
用线段树维护右端点的答案,再从后往前移动左端点,在考虑在左边加入一个点的答案
对右端点的贡献的影响 $影响为 a - c[i]$
$max(d[i + 1] - d[i]) ^2 这部分的影响可以用单调栈维护某个区间的最大值是多少$
$因为每个值只会被操作两次,复杂度O(nlogn)$
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 300010
#define INFLL 0x3f3f3f3f3f3f3f3f
int n;
ll a, c[N], d[N];
ll val[N];
struct node
{
ll v; int l, r;
node () {}
node (ll v, int l, int r) : v(v), l(l), r(r) {}
}; namespace SEG
{
struct node
{
ll lazy, Max;
node () {}
node (ll lazy, ll Max) : lazy(lazy), Max(Max) {}
void init() { lazy = Max = ; }
void add(ll v)
{
lazy += v;
Max += v;
}
node operator + (const node &other) const
{
node res; res.init();
res.Max = max(Max, other.Max);
return res;
}
}a[N << ];
void init() { memset(a, , sizeof a); }
void pushdown(int id)
{
if (!a[id].lazy) return;
a[id << ].add(a[id].lazy);
a[id << | ].add(a[id].lazy);
a[id].lazy = ;
}
void update(int id, int l, int r, int ql, int qr, ll v)
{
if (l >= ql && r <= qr)
{
a[id].add(v);
return;
}
int mid = (l + r) >> ;
pushdown(id);
if (ql <= mid) update(id << , l, mid, ql, qr, v);
if (qr > mid) update(id << | , mid + , r, ql, qr, v);
a[id] = a[id << ] + a[id << | ];
}
ll query(int id, int l, int r, int ql, int qr)
{
if (l >= ql && r <= qr) return a[id].Max;
int mid = (l + r) >> ;
pushdown(id);
ll res = ;
if (ql <= mid) res = max(res, query(id << , l, mid, ql, qr));
if (qr > mid) res = max(res, query(id << | , mid + , r, ql, qr));
return res;
}
} int main()
{
while (scanf("%d%lld", &n, &a) != EOF)
{
for (int i = ; i <= n; ++i) scanf("%lld%lld", d + i, c + i);
for (int i = ; i <= n; ++i) val[i] = (d[i] - d[i - ]) * (d[i] - d[i - ]);
SEG::init();
stack <node> sta;
ll res = ;
for (int i = n; i >= ; --i)
{
SEG::update(, , n, i, n, a - c[i]);
if (i != n)
{
node now = node(val[i + ], i + , i + );
while (!sta.empty())
{
node tmp = sta.top();
if (now.v >= tmp.v)
{
SEG::update(, , n, tmp.l, tmp.r, tmp.v);
now.r = tmp.r;
sta.pop();
}
else
break;
}
SEG::update(, , n, now.l, now.r, -now.v);
sta.push(now);
}
res = max(res, SEG::query(, , n, i, n));
sta.push(node(, i, i));
}
printf("%lld\n", res);
}
return ;
}
Educational Codeforces Round 59 Solution的更多相关文章
- Educational Codeforces Round 59 (Rated for Div. 2) DE题解
Educational Codeforces Round 59 (Rated for Div. 2) D. Compression 题目链接:https://codeforces.com/contes ...
- Educational Codeforces Round 59 (Rated for Div. 2) E 区间dp + 状态定义 + dp预处理(分步dp)
https://codeforces.com/contest/1107/problem/E 题意 给出01字符串s(n<=100),相邻且相同的字符可以同时消去,一次性消去i个字符的分数是\(a ...
- C. Brutality Educational Codeforces Round 59 (Rated for Div. 2) 贪心+思维
C. Brutality time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- Educational Codeforces Round 59
B. Digital root 题意: 题目定义了x的digital root是S(x).S(5)=5,S(38)=S(3+8=11)=S(1+1+2)=2. 有n个询问,每次询问给出ki和xi,要你 ...
- Educational Codeforces Round 56 Solution
A. Dice Rolling 签到. #include <bits/stdc++.h> using namespace std; int t, n; int main() { scanf ...
- Educational Codeforces Round 57 Solution
A. Find Divisible 签到. #include <bits/stdc++.h> using namespace std; int t, l, r; int main() { ...
- Educational Codeforces Round 58 Solution
A. Minimum Integer 签到. #include <bits/stdc++.h> using namespace std; #define ll long long ll l ...
- Educational Codeforces Round 59 (Rated for Div. 2)
熬夜爆肝,智商急剧下降 坐标UTC+8晚上23:35开始 晚上脑袋转的慢,非常慢 T1上来先做还花了好几分钟 T2本来是有式子的我TM写数位DP写炸了然后才发现是有公式 T3英语不好,一开始题意没读懂 ...
- 【考试记录】Educational Codeforces Round 59 (Rated for Div. 2)
本来准备划水,结果被垃圾题艹翻了…… T2题意: 定义一个数$x$的数字根$S(x)$为:将其各位数字相加得到一个新数,再将新数的数字和相加直到得到一个个位数,就是该数的数字根. 例如:$S(38)= ...
随机推荐
- swift - UIAlertView 的用法
1,创建一个alertview,并带有“确定”和“取消”两个按钮 (注:在这里使用alertview,会报警告,那是因为从ios 8 以后,建议使用UIAlertviewController) //警 ...
- laravel安装 redis 并驱动 session
1)composer 安装 redis composer require predis/predis 如果感兴趣,可以看一下这里 2)配置 redis 连接(config/database.php 配 ...
- ch6-定制数据对象(打包代码和数据)
为了看出数据属于哪个选手,教练向各个选手的数据文件中添加了标识数据:选手全名,出生日期,计时数据. 例如:sarah文件的数据更新为: Sarah Sweeney,2002-6-17,2:58,2.5 ...
- C++11新特性之六——元编程
C++11新特性之六——元编程
- IE8及以下的数组处理与其它浏览器的不同
在解决search-box的bug时,由于IE8-的数组处理与其它浏览器的不同,而导致报错. 示例:arr=[1,3,3,]; 当数组的最后是一个逗号时: IE9+默认 arr=[1,3,3];也就是 ...
- console输出图案
探索天猫控制台下的图案是怎么制作的 通过它的源码找到以下代码(还原解压代码) 自己也照葫画瓢搞了个以前公司的logo
- C#文件下载的几种方式
第一种:最简单的超链接方法,<a>标签的href直接指向目标文件地址,这样容易暴露地址造成盗链,这里就不说了 1.<a>标签 <a href="~/Home/d ...
- 【UOJ274】【清华集训2016】温暖会指引我们前行 LCT
[UOJ274][清华集训2016]温暖会指引我们前行 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很 ...
- Windows Phone 在读取网络图片之前先显示默认图片
1.新建一个控件WindowsPhoneControl1 WindowsPhoneControl1.xaml <UserControl x:Class="DefaultImage.Wi ...
- 精简的webservice
看了网上好多关于webservice的例子,基本上对初学者来说都是模棱两可云里雾里,现在,我将网上关于webservice的讲解提炼出来,通过一个最简单使用并且方便的例子,告诉大家什么是webserv ...