原题目地址(牛客)

Identical Day

题目大意

给定一个长度为 \(n\) 的 \(01\) 串,对于每段长度为 \(l\) 的连续的 \(1\) ,其权值为 \(\frac{l\times(l+1)}{2}\) ,对于给出的 \(01\) 串显然可得其权值和。现在你能够将该串中任意的 \(1\) 改为 \(0\) ,问最少改多少次你能使得新串的权值和不超过 \(k\) 。

分析

首先,对于此题,需要知道,对于一个连续 \(1\) 串,在其中更改的时候如何使得效率更高?要到达最好的效果,我们必须要让该串在更改后被分成的几个连续 \(1\) 串含有 \(1\) 的数量尽量平均。

例如:

11111 \\只能更改两个1,如何更改使得效果最好?
10101 \\更改前,权值为15,现在权值为3
11111111111111111 \\只能更改两个1,如何使得更改效果最好?
11101110111101111 \\更改前,权值为105,现在权值为32

注意要尽量平均,如第二个例子,就不能是 \(11101110111011111\) ,这样权值是 \(33\) 。

知道了这一点,接下来我们想想这道题怎么做?

一开始,我们或许会想到使用一个大根堆,将每一段入堆,每次取出最长的一段来平均分,分出来的小段又分别入队。

这么贪心显然是错误的,错在哪里?有可能我们的方案并非最优。

例如:

1111111 \\设其为原串中的一段连续1串
1110111 \\第一次更改
1010111 \\按照我们上述的贪心方案第二次更改会变成这样
1011011 \\实际上更改两个最优应该是这样

那应该怎么办?

保留最开始的大根堆思路,我们可以将一个 \(01\) 串内的每个连续 \(1\) 串单独包装,计算其砍一刀的贡献,砍两刀的贡献(注意砍两刀的贡献是相对于已经砍了一刀的权值)。我们可以重载大根堆运算为贡献大的优先,这样,我们一刀一刀砍,肯定是最优的。

这么做的好处是:

1111111 \\设其为原串中的一段连续1串
1110111 \\第一次更改
1011011 \\若我们发现该段还需要二次更改我们不会管第一次更改,直接在最开始的基础上更改两次,得到最优方案

CODE

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w*=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
struct node{
int l; //该段长度
int v; //当前阶段改变数
int nex; //至下一阶段变化量
int val;
bool operator < (const node &x)const{ //重载运算符
if(nex<x.nex) return 1;
return 0;
}
};
int n,k,ans;
int unhappy; //储存目前的不开心值
int a[N];
priority_queue<node> q;
inline void solve()
{
while(unhappy>k){
node now=q.top(),add;
q.pop(); //出堆
ans+=1; //更新答案
unhappy-=now.nex; //更新不快乐值
int ad=(now.l-now.v-1)/(now.v+2),lv=(now.l-now.v-1)%(now.v+2),temp=0;
for(int i=1;i<=lv;i++) temp=temp+(ad+1)*(ad+2)/2;
for(int i=1;i<=now.v+2-lv;i++) temp=temp+ad*(ad+1)/2;
add.val=temp;
add.nex=now.val-temp;
add.l=now.l;
add.v=now.v+1;
q.push(add);
}
}
int main()
{
n=read(),k=read();
for(int i=1;i<=n;i++){
char x=getchar();
a[i]=x-'0';
}
int now=0;
for(int i=1;i<=n+1;i++){
if(a[i]) now++;
else if(now){
int temp=now*(now+1)/2; //记录该段在不改变情况下对不开心值的贡献
int l1=(now-1)/2,l2=(now-1)-l1; //最佳的两段
unhappy+=temp;
node add; //处理入堆元素
add.l=now,now=0;
add.v=1;
add.nex=temp-(l1*(l1+1)+l2*(l2+1))/2; //改变一次对答案的最大贡献
add.val=(l1*(l1+1)+l2*(l2+1))/2;
q.push(add); //入大根堆
}
} solve();
printf("%d\n",ans);
return 0;
}

I-Identical Day[题解]的更多相关文章

  1. UVALive 6124 Hexagon Perplexagon 题解

    http://vjudge.net/problem/viewProblem.action?id=37480 East Central Regional Contest Problem C: Hexag ...

  2. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

  3. Codeforces Round #469 Div. 2题解

    A. Left-handers, Right-handers and Ambidexters time limit per test 1 second memory limit per test 25 ...

  4. AtCoder Beginner Contest 089完整题解

    A - Grouping 2 Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement There a ...

  5. ICPC — International Collegiate Programming Contest Asia Regional Contest, Yokohama, 2018–12–09 题解

    目录 注意!!此题解存在大量假算法,请各位巨佬明辨! Problem A Digits Are Not Just Characters 题面 题意 思路 代码 Problem B Arithmetic ...

  6. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  7. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  8. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  9. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  10. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

随机推荐

  1. KVO后[obj class]与object_getClass(id obj)的结果竟会不一致?

    说说背景,研究下面的代码时,KVO后[obj class]与object_getClass(id obj)的结果竟会不一致? PersonModel *aPersonModel = [[PersonM ...

  2. gin使用validator库参数校验若干实用技巧

    validator库参数校验若干实用技巧 本文介绍了使用validator库做参数校验的一些十分实用的使用技巧,包括翻译校验错误提示信息.自定义提示信息的字段名称.自定义校验方法等. validato ...

  3. Spring4

    Spring javaEE开发一站式框架 web层:SpringMVC Service层:Spring的Bean管理(IoC).Spring声明式事务 Dao层:Spring的jdbc模板.Sprin ...

  4. 【Javascript + Vue】实现对任意迷宫图片的自动寻路

    前言 可以直接体验最终效果:https://maze-vite.vercel.app/ 寻路前: 寻路后,自动在图片上生成红色路径,蓝色是探索过的区域: 这里我故意用手机斜着角度拍,就是为了展示程序完 ...

  5. robotframework用户关键字创建过程

    robotframework是一个关键字驱动框架,核心在于关键字的应用.系统本身通过各种库自带了大量关键字,同时支持用户自定义关键字.关键字可以简单理解为各种处理数据的方法. 关键字区别与用户参数. ...

  6. 从 SQL 到 MongoDB,这一篇就够了

    很多开发者首次接触数据库(通常是在高校课堂)的概念,或者说接触第一个数据库,通常是 SQL 数据库,而现在,NoSQL 数据库后来居上,很多原 SQL 数据的使用者难免有转向 NoSQL 的需求.而作 ...

  7. 【题解】滑雪 luogu1434 记忆化搜索

    记忆化搜索入门题 题目 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在 ...

  8. 透彻理解液晶显示模组LCD1602指令集与驱动编程(1)

    LCD1602可以说是大多数单片机工程师了解液晶显示的入门级模组,其显示原理与其它很多显示模组也是相似的,今天我们就来详细讨论一下它的指令集.所谓模组的指令集,本质上是该模组使用的控制芯片的指令集,本 ...

  9. gRPC趁现在还没大火,抢先了解一下

    前言 系统分布式已经成为程序员的家常,将大型单体划分为相对简单的小模块,分散系统能力,提升系统扩展性.功能模块复用性等:各功能模块之间肯定会有很多数据共享和交互的应用场景,那就避免不了各模块之间的通信 ...

  10. hdu1232 并查集总结

    前言 在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中. 这一类问题其特点是看似并 ...