Codeforces Round 958 (Div. 2)

题目链接:Codeforces Round 958 (Div. 2)

总结:C因为常数没转longlong wa两发,难绷。

A. Split the Multiset

fag:模拟

Description:给定一个n和一个k,每次可以将n减掉一个数u,然后插入x个数,x<=k,并且插入的数之和等于u。求将其转化为全1的最小操作次数。

Solution:因为最后要得到全1,所以每次操作我们插入尽可能多的1,即插入1,1,...,u(k1)。相当于每次将n减少k1。那么答案为k,(n1+k1)/k,这里是向上取整。

void solve(){
cin >> n >> k;
k --;
if (n == 1){
cout << 0 << endl;
return;
}
n --;
cout << (n + k - 1) / k << endl;
}

B. Make Majority

fag: 思维

Description: 给定一个只含01的字符串,每次操作可以选择一个区间l,r,将这个区间变为一个数(区间内出现次数最多的数)。

问能否将其变为1

Solution:手摸几组样例发现:我们可以把所有连续的多个0变为一个0,如果我们需要将一个0去掉,那么至少需要两个1

  • 那么统计连续0的区间个数x1的个数y
  • y>=x+1时,有解,否则无解。
void solve(){
cin >> n;
cin >> s;
int x = 0, y = 0;
for (int i = 0; i < n; i ++){
if (s[i] == '0')
x ++;
else
y ++;
}
int xx = 0;
bool flag = true;
for (int i = 0; i < n; i ++){
if (s[i] == '0' && flag){
xx ++;
flag = false;
continue;
}
if (s[i] == '1')
flag = true;
}
if (y >= xx + 1){
cout << "Yes\n";
}
else{
cout << "No\n";
}
}

C. Increasing Sequence with Fixed OR

fag:位运算

Description:给定一个n,求一个最长的序列,序列满足ai<ai+1,且ai|ai+1==1。输出序列的长度和序列值。

Solution:显然我们需要将n转化为二进制。模拟样例后发现,如果n的二进制含有x1,那么序列长度为x+1

然后考虑如何构造。我们只需要依次去掉低位1,就可以满足以上要求。注意对常数进行位运算时,需要将其强制转化为long long

void solve(){
cin >> n;
vector<int> ans;
ans.eb(n);
for (int i = 0; i < 64; i ++){
if (n >> i & 1){ // 这一位是1
ans.eb(n ^ (1LL << i)); // 注意这里
}
}
if (ans[ans.size() - 1] == 0) // 注意特判
ans.pop_back();
cout << ans.size() << endl;
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); i ++){
cout << ans[i] << " ";
}
cout << endl;
}

D. The Omnipotent Monster Killer

fag:树形DP

Description:一颗有n个点的数,每个点有一个权值ai,每回合所有点会对玩家造成大小为自身权值的伤害。玩家每回合可以消灭一些点(不能删除被一条边相连的两点)。求玩家受到的最小伤害。

1 <= n <= 3e5
1 <= ai <= 1e12

Solution:只需要最多L个回合即可,L<=log2n+1,我们令L=20即可,不太会证。

  • 如果一个节点在第i个回合删除,那么它的伤害为iai

  • f[x][j]表示,x节点在第j个回合删除,以x为根的子树的伤害最小值。f[x][j]=jax+ison(x)min(f[i][k]),k!=j

  • 答案ans: min(f[0][j],1<=j<=20)

void solve(){
cin >> n;
vector<int> a(n);
vector g(n, vector<int>());
vector f(n, vector<int>(21, 0));
for (int i = 0; i < n; i ++)
cin >> a[i];
for (int i = 0; i < n - 1; i ++){
int a, b;
cin >> a >> b;
a --, b --;
g[a].eb(b), g[b].eb(a);
}
auto dfs = [&](auto self, int u, int v) -> void {
for (int i = 1; i <= 20; i ++){
f[u][i] = i * a[u];
}
for (auto x : g[u]){
if (x == v)
continue;
self(self, x, u);
for (int i = 1; i <= 20; i ++){
int mi = 1e18;
for (int j = 1; j <= 20; j ++){
if (i == j)
continue;
mi = min(mi, f[x][j]);
}
f[u][i] += mi;
}
}
};
dfs(dfs, 0, -1);
int ans = 1e18;
for (int i = 1; i <= 20; i ++){
ans = min(ans, f[0][i]);
}
cout << ans << endl;
}
posted @   Sakura17  阅读(232)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示