Identical Day 题解(思维)

Posted hunxuewangzi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Identical Day 题解(思维)相关的知识,希望对你有一定的参考价值。

题目连接

题目大意

给你一个长度为\\(n(n\\leq1e5)\\)\\(01\\)

求最少使得多少个\\(1\\)变为\\(0\\)后这个串的价值小于\\(k(k\\le1e10)\\)

串的价值为所有连续为\\(1\\)的串的价值

一段长度为\\(len\\)连续为\\(1\\)的价值为\\(len*(len+1)/2\\)

例如\\(0111101\\)的价值为\\(\\frac{4\\times5}{2}+\\frac{1\\times2}{2}=11\\)

题目思路

这个题目我一开始想的过于简单了,首先我认为很容易想到优先队列贪心

我用的是每次拿出最长的那一段然后直接中间分隔,用优先队列去维护

但是可以想一下如果一段要分为三段,那么最终我分的比例等于\\(1:1:2\\)

但是显然是要\\(1:1:1\\) 即三等分,但是我那样第一步是分为两份肯定不行

然后我就不不会了。。。

其实正解和这个差不了太多,就是差值最大

\\(cal(a,b)\\)为一段长度为\\(a\\)的连续的\\(1\\),中间人为变了\\(b\\)个的最小价值

\\((a,b)\\)这个放入优先队列,那么优先队列只要比较\\(cal(a,b)-cal(a,b+1)\\)即可

\\(cal(a,b)\\)这个函数计算也很简单\\(b\\)\\(0\\),那么分为\\(b+1\\)

肯定是要等分每一份为\\(x=(a-b)/(b+1)\\),而多余了\\(y=(a-b)\\%(b+1)\\)

那么肯定是给\\(y\\)份每一个多\\(1\\)

  • \\((b+1-y)\\)份长度为$x $
  • \\(y\\)份长度为\\(x+1\\)

以前写过类似的题目,感觉这种题目就是要往差值方面去考虑,不过这个稍微难一点点

代码

#include<bits/stdc++.h>
#define debug printf("\\n I am here\\n");
#define fi first
#define se second
#define pii pair<int,int>
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=0x3f3f3f3f3f3f3f3f;
using namespace std;
ll n,k;
char s[maxn];
ll cal(ll a,ll b){
    // 长度为a个1 中间有b个0
    ll x=(a-b)/(b+1);
    ll y=(a-b)%(b+1);
    ll ans=x*(x+1)/2*(b+1-y)+(x+1)*(x+2)/2*y;
    return ans;
}
ll dif(ll a,ll b){
    return cal(a,b)-cal(a,b+1);
}
struct node{
    ll x,y;
    friend bool operator<(node a,node b){
        return dif(a.x,a.y)<dif(b.x,b.y);
    }
};
priority_queue<node> pq;
int main(){
    scanf("%lld%lld",&n,&k);
    scanf("%s",s+1);
    ll len=0,sum=0;
    for(int i=1;i<=n;i++){
        if(s[i]==\'1\'){
            len++;
        }
        if(s[i]==\'0\'||i==n){
            if(len!=0){
                sum+=len*(len+1)/2;
                pq.push({len,0});
            }
            len=0;
        }
    }
    ll ans=0;
    while(sum>k){
        ans++;
        node temp=pq.top();
        pq.pop();
        sum-=dif(temp.x,temp.y);
        if(temp.x==temp.y+1) continue;
        pq.push({temp.x,temp.y+1});
    }
    printf("%lld\\n",ans);
    return 0;
}

以上是关于Identical Day 题解(思维)的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2017题解

算法·每日一题(详解+多解)-- day14

算法·每日一题(详解+多解)-- day14

一篇文章带你搞懂回溯(万字:核心思维+图解+习题+题解思路+代码注释)

一篇文零基础带你搞懂回溯(万字:核心思维+图解+习题+题解思路+代码注释)

一篇文零基础带你搞懂回溯(万字:核心思维+图解+习题+题解思路+代码注释)