Codeforces Round #530 (Div. 2) Solution
A. Snowball
签。
#include <bits/stdc++.h>
using namespace std; int w, h, u[], d[]; int main()
{
while (scanf("%d%d", &w, &h) != EOF)
{
for (int i = ; i < ; ++i) scanf("%d%d", u + i, d + i);
for (int i = h; i >= ; --i)
{
w += i;
for (int j = ; j < ; ++j) if (i == d[j])
{
w -= u[j];
w = max(w, );
}
}
printf("%d\n", w);
}
return ;
}
B. Squares and Segments
签.
#include <bits/stdc++.h>
using namespace std; int n;
int main()
{
while (scanf("%d", &n) != EOF)
{
int limit = sqrt(n);
int res = 1e9;
for (int i = ; i <= limit; ++i)
res = min(res, i + n / i + (n % i ? : ));
printf("%d\n", res);
}
return ;
}
C. Postcard
Solved.
题意:
一个不定字符串,
如果有一位上有糖果,那么它前面那一个字符可以选择留下获得丢失
如果有一位上有雪花,那么它前面那一个字符可以选择留下、丢失或者重复x次,x自定
问能否由一种合法的选择,使得确定后的字符串的长度为n
思路:
先排除两种情况,
第一种是去掉所有可以去掉的字符后,长度都大于n
第二种是保留所有的不定字符,并且没有雪花,此时长度小于n
那么其他情况都是可以构造的
考虑两种情况
第一种 没有雪花,那么只需要删掉一些字符使得满足题意,不合法情况在之前已经排除
第二种 有雪花,保留一个雪花字符,删掉其他字符,用雪花字符的重复来填充长度
#include <bits/stdc++.h>
using namespace std; #define N 1010
char s[N];
int n, len; int main()
{
while (scanf("%s", s + ) != EOF)
{
scanf("%d", &n);
len = strlen(s + );
int snow = , candy = ;
for (int i = ; i <= len; ++i)
{
if (s[i] == '*') ++snow;
if (s[i] == '?') ++candy;
}
if (len - * (snow + candy) > n) puts("Impossible");
else if (len - candy < n && snow == ) puts("Impossible");
else
{
string res = "";
if (snow == )
{
int needdel = len - candy - n;
for (int i = ; i <= len; ++i)
{
if (s[i] == '?') continue;
if (i != len && s[i + ] == '?')
{
if (needdel) --needdel;
else res += s[i];
}
else res += s[i];
}
}
else
{
int flag = true;
int needadd = n - (len - * (candy + snow));
for (int i = ; i <= len; ++i)
{
if (i != len && s[i + ] == '?') continue;
if (i != len && s[i + ] == '*' && !flag) continue;
if (s[i] == '?' || s[i] == '*') continue;
if (i != len && s[i + ] == '*')
{
flag = false;
while (needadd--) res += s[i];
}
else res += s[i];
}
}
cout << res << endl;
}
}
return ;
}
D. Sum in the tree
Solved.
题意:
有一棵树,有点权,知道奇数层所有点的到根的前缀点权和,偶数层的不知道
求如何分配点权使得满足限制条件并且所有点权和最小
思路:
尽量将点权分配给深度低的,因为这样它产生的贡献肯定比分给深度大的要高
那么一个偶数层点u最多可以分配的点权就是
$Min(s[v] - s[fa[u]])\ v为它的儿子$
判-1也很好判,上面这个Min值如果是负的就不行,因为点权大于等于0
对于奇数层点的话 直接算它点权
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 100010
int n, s[N];
vector <int> G[N];
bool flag; ll res; ll dist[N];
void DFS(int u, int fa)
{
if (s[u] == -)
{
if (G[u].size() == ) return;
ll Min = (ll)1e18;
for (auto v : G[u]) if (v != fa)
Min = min(Min, s[v] - dist[fa]);
if (Min < )
{
flag = false;
return;
}
res += Min;
dist[u] = dist[fa] + Min;
}
else
{
dist[u] = s[u];
res += dist[u] - dist[fa];
}
for (auto v : G[u]) if (v != fa)
{
DFS(v, u);
if (!flag) return;
}
} int main()
{
while (scanf("%d", &n) != EOF)
{
flag = true; res = ;
for (int i = ; i <= n; ++i) G[i].clear();
for (int i = , p; i <= n; ++i)
{
scanf("%d", &p);
G[i].push_back(p);
G[p].push_back(i);
}
for (int i = ; i <= n; ++i) scanf("%d", s + i);
DFS(, );
if (!flag) res = -;
printf("%lld\n", res);
}
return ;
}
E. Nice table
Upsolved.
题意:
构造一个$n * m的字符串矩阵,只包含'A', 'G', 'C', 'T'$
使得$任意2 \cdot 2 的子矩形都包含'A', 'G', 'C', 'T'$
并且要与给出的矩阵不同的字符个数最少
思路:
要求满足$任意2 \cdot 2 的子矩形都包含'A', 'G', 'C', 'T'$
的矩阵要满足每一行都是由两个字符交替组成
或者每一列都是由两个字符交替组成
枚举即可
#include <bits/stdc++.h>
using namespace std; #define N 150010
int n, m, p;
string s[N];
string t[][] =
{
{
"AG",
"AC",
"AT",
"GC",
"GT",
"CT",
},
{
"CT",
"GT",
"CG",
"AT",
"AC",
"AG",
}
};
string res[][N]; void work_row(string a, string b)
{
for (int i = ; i < n; ++i) res[p][i].clear();
string tmp[];
int cnt[];
for (int i = ; i < n; ++i)
{
tmp[] = tmp[] = "";
cnt[] = cnt[] = ;
for (int j = ; j < m; ++j)
for (int k = ; k < ; ++k)
tmp[k] += (i & ) ? a[j % ^ k] : b[j % ^ k];
for (int j = ; j < m; ++j)
for (int k = ; k < ; ++k)
cnt[k] += tmp[k][j] != s[i][j];
if (cnt[] < cnt[])
res[p][i] = tmp[];
else
res[p][i] = tmp[];
}
++p;
} void work_col(string a, string b)
{
for (int i = ; i < n; ++i) res[p][i].clear();
string tmp[];
int cnt[];
for (int j = ; j < m; ++j)
{
tmp[] = tmp[] = "";
cnt[] = cnt[] = ;
for (int i = ; i < n; ++i)
for (int k = ; k < ; ++k)
tmp[k] += (j & ) ? a[i % ^ k] : b[i % ^ k];
for (int i = ; i < n; ++i)
for (int k = ; k < ; ++k)
cnt[k] += tmp[k][i] != s[i][j];
if (cnt[] < cnt[])
for (int i = ; i < n; ++i)
res[p][i] += tmp[][i];
else
for (int i = ; i < n; ++i)
res[p][i] += tmp[][i];
}
++p;
} int com(int x)
{
int tmp = ;
for (int i = ; i < n; ++i)
for (int j = ; j < m; ++j)
tmp += res[x][i][j] != s[i][j];
return tmp;
} int main()
{
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
while (cin >> n >> m)
{
p = ;
for (int i = ; i < n; ++i) cin >> s[i];
for (int i = ; i < ; ++i)
work_row(t[][i], t[][i]);
for (int i = ; i < ; ++i)
work_col(t[][i], t[][i]);
int Min = (int)1e9, pos = -;
for (int i = ; i < ; ++i)
{
//puts("bug");
//for (int j = 0; j < n; ++j) cout << res[i][j] << "\n";
int tmp = com(i);
//cout << tmp << "\n";
if (tmp < Min)
{
Min = tmp;
pos = i;
}
}
for (int i = ; i < n; ++i) cout << res[pos][i] << "\n";
}
return ;
}
F. Cookies
Upsolved.
题意:
刚开始有一个砝码在根节点,两个玩家,
先手玩家可以选择将它移向它的某个儿子,
后手玩家可以选择移除掉通向它某个儿子的边,当然也可以选择跳过这个操作
先手玩家可以选择在什么时候停下来,并且回到根节点,回去的过程可以吃饼干
每个结点有饼干数量,以及吃掉该节点上的一块饼干需要的时间
吃饼干需要时间,在边上走也需要时间,总时间T的情况下吃到的最多的饼干
求双方都在最优操作下,先手玩家吃到的饼干的最多的数量
思路:
先处理出每个结点回去的答案,再二分答案,十分显然
怎么处理答案,
对于点u, 首先吃饼干的时间是$T - 2 * dist(root, u)$
那么用权值BIT维护时间,以及饼干数量,二分查找在剩余时间的可以吃的最大饼干数量
注意处理尾部的部分
再二分答案,dp验证
考虑什么样的情况是合理的,我们假定某一个点是必胜态,那么这个点的深度如果<=1,
那么先手必胜,因为先手先移动
再考虑哪些点是必胜态,如果该点的处理出的饼干数量$ > limit$ 那么就是必胜态
又或者该点有2个儿子以上的点是必胜态,该点也是必胜态,因为后手玩家每次只能删去一条边
递归判断即可
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 100010
#define M 1000010
int n; ll T;
int x[N], t[N], l[N];
vector <int> G[N]; namespace BIT
{
ll val[M], sum[M], a[M];
void init()
{
memset(val, , sizeof val);
memset(sum, , sizeof sum);
memset(a, , sizeof a);
}
void update(int x, ll v)
{
ll sumv = v * x;
a[x] += v;
for (; x < M; x += x & -x)
{
val[x] += v;
sum[x] += sumv;
}
}
ll query(ll T)
{
int l = , r = M - ;
ll res = ;
while (r - l >= )
{
int mid = (l + r) >> ;
int x = mid;
ll score = , sumt = ;
for (; x; x -= x & -x)
{
score += val[x];
sumt += sum[x];
}
if (sumt <= T)
{
score += min(a[mid + ], ((T - sumt) / (mid + )));
res = score;
l = mid + ;
}
else
r = mid - ;
}
return res;
}
} int fa[N], deep[N];
ll dist[N], score[N];
void DFS(int u)
{
for (auto v : G[u]) if (v != fa[u])
{
deep[v] = deep[u] + ;
dist[v] = dist[u] + l[v];
BIT::update(t[v], x[v]);
score[v] = BIT::query(T - 2ll * dist[v]);
DFS(v);
BIT::update(t[v], -x[v]);
}
} bool vis[N];
void dp(int u, ll x)
{
if (score[u] >= x)
{
vis[u] = ;
return;
}
int cnt = ;
for (auto v : G[u]) if (v != fa[u])
{
dp(v, x);
cnt += vis[v];
}
if (cnt >= ) vis[u] = ;
} bool check(ll x)
{
memset(vis, , sizeof vis);
dp(, x);
for (int i = ; i <= n; ++i) if (deep[i] <= && vis[i])
return ;
return ;
} void init()
{
for (int i = ; i <= n; ++i) G[i].clear();
BIT::init();
} int main()
{
while (scanf("%d%lld", &n, &T) != EOF)
{
init();
for (int i = ; i <= n; ++i) scanf("%d", x + i);
for (int i = ; i <= n; ++i) scanf("%d", t + i);
for (int i = ; i <= n; ++i)
{
scanf("%d%d", fa + i, l + i);
G[i].push_back(fa[i]);
G[fa[i]].push_back(i);
}
BIT::update(t[], x[]); score[] = BIT::query(T); dist[] = ; deep[] = ;
DFS();
ll l = , r = (ll)1e11 + , res = ;
while (r - l >= )
{
ll mid = (l + r) >> ;
if (check(mid))
{
res = mid;
l = mid + ;
}
else
r = mid - ;
}
printf("%lld\n", res);
}
return ;
}
Codeforces Round #530 (Div. 2) Solution的更多相关文章
- Codeforces Round #466 (Div. 2) Solution
从这里开始 题目列表 小结 Problem A Points on the line Problem B Our Tanya is Crying Out Loud Problem C Phone Nu ...
- 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution
对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...
- Codeforces Round #545 (Div. 1) Solution
人生第一场Div. 1 结果因为想D想太久不晓得Floyd判环法.C不会拆点.E想了个奇奇怪怪的set+堆+一堆乱七八糟的标记的贼难写的做法滚粗了qwq靠手速上分qwqqq A. Skyscraper ...
- Codeforces Round #530 (Div. 2) F (树形dp+线段树)
F. Cookies 链接:http://codeforces.com/contest/1099/problem/F 题意: 给你一棵树,树上有n个节点,每个节点上有ai块饼干,在这个节点上的每块饼干 ...
- Codeforces Round #530 (Div. 2) A,B,C,D
A. Snowball 链接:http://codeforces.com/contest/1099/problem/A 思路:模拟 代码: #include<bits/stdc++.h> ...
- Codeforces Round 500 (Div 2) Solution
从这里开始 题目地址 瞎扯 Problem A Piles With Stones Problem B And Problem C Photo of The Sky Problem D Chemica ...
- Codeforces Round #530 (Div. 2):D. Sum in the tree (题解)
D. Sum in the tree 题目链接:https://codeforces.com/contest/1099/problem/D 题意: 给出一棵树,以及每个点的si,这里的si代表从i号结 ...
- Codeforces Round #530 (Div. 2) F 线段树 + 树形dp(自下往上)
https://codeforces.com/contest/1099/problem/F 题意 一颗n个节点的树上,每个点都有\(x[i]\)个饼干,然后在i节点上吃一个饼干的时间是\(t[i]\) ...
- Codeforces Round #607 (Div. 1) Solution
从这里开始 比赛目录 我又不太会 div 1 A? 我菜爆了... Problem A Cut and Paste 暴力模拟一下. Code #include <bits/stdc++.h> ...
随机推荐
- ArcGIS Server密码丢失
http://jingyan.baidu.com/article/1e5468f90f6465484961b70d.html 1.cd D:\Program Files\ArcGIS\Server\t ...
- 【RF库Collections测试】Set To Dictionary
Name:Set To DictionarySource:Collections <test library>Arguments:[ dictionary | *key_value_pai ...
- 编译OSG的FreeType插件时注意的问题
使用自己编译的freetype.lib,在编译osgdb_freetype插件项目时,报错LINK错误,找不到png的一堆函数 最简单的方式是不要使用PNG编译freetype.记住不要犯贱.
- ThreadUtil 多线程处理List,回调处理具体的任务
每次想多线程处理一个大的结果集的时候 都需要写一大堆代码,自己写了个工具类 方便使用 package com.guige.fss.common.util; import com.guige.fss.c ...
- 使用ASIHTTPRequest xcode编译提示找不到"libxml/HTMLparser.h"
使用ASIHTTPRequest xcode编译提示找不到"libxml/HTMLparser.h",解决方法如下: 1>.在xcode中左边选中项目的root节点,在中间编 ...
- UITableView取消选中颜色、常用操作
UITableView取消选中颜色.常用操作 使用空白view取代cell - (UITableViewCell *)tableView:(UITableView *)tableView cell ...
- Android 多状态按钮ToggleButton
1.什么是ToggleButtonToggleButton有两种状态:选中和未选中状态并且需要为不同的状态设置不同的显示文本2.ToggleButton属性android:checked=" ...
- MySql学习—— 查询性能优化 深入理解MySql如何执行查询
本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...
- 关于Android原生Email的自己的一些认识
http://blog.csdn.net/gloryhero/article/details/47259583 Email的框架图: Email 包含3个包:Eamil.Exchagne.Unifie ...
- ubuntu14.04 LTS 搜狗输入法安装和不能输入中文的解决方法
搜狗输入法安装 1.首先通过Ubuntu软件中心,需要安装:fcitx https://pinyin.sogou.com/linux/help.php 2.然后再安装搜狗输入法包 https://pi ...