• [loj3523]分糖果


    做法1

    将问题离线,并在左端点和右端点打上差分,之后即可以看作求$f(C,[a_{1},a_{2},...,a_{n}])$,其表示以$C$为上限(0为下限),从0开始不断加上$a_{i}$(可以为负)的答案

    再定义$g(C,a_{i})$,其与$f(C,a_{i})$的定义类似,但没有下限为0的限制

    考虑两者的关系,显然$forall 0le jle n$有
    $$
    f(C,[a_{1},a_{2},...,a_{n}])ge f(C,[a_{j+1},a_{j+2},...,a_{n}])ge g(C,[a_{j+1},a_{j+2},...,a_{n}])
    $$
    前者是因为在操作$a_{j-1}$后值非负,后者因为其没有下限显然值不增

    另一方面,考虑最大的$j$,使得在$f(C,a_{i})$中操作$a_{j}$后值为0,即之后不会再变为0,那么也可以看作没有下限为0的限制,即有
    $$
    f(C,[a_{1},a_{2},...,a_{n}])=f(C,[a_{j+1},a_{j+2},...,a_{n}])=g(C,[a_{j+1},a_{j+2},...,a_{n}])
    $$
    (若不存在则令$j=0$,相等的原因类似,这里就省略了)

    由此,我们得到了$f(C,[a_{1},a_{2},...,a_{n}])=max_{0le jle n}g(C,[a_{j+1},a_{j+2},...,a_{n}])$

    考虑$g(C,[a_{1},a_{2},...,a_{n}])$,令$S_{i}=sum_{j=1}^{i}a_{j}$,若不存在$S_{i}>C$即为$S_{n}$,否则即$S_{n}-max_{1le ile n}S_{i}+C$

    将之代入前式并化简,也即
    $$
    f(C,[a_{1},a_{2},...,a_{n}])=S_{n}-min_{0le ile n}max(S_{i},max_{ile jle n}S_{j}-C)
    $$
    考虑如何维护,二分枚举答案$T$,那么$f(C,a_{i})>T$当且仅当
    $$
    exists 0le ile n,max(S_{i},max_{ile jle n}S_{j}-C)<S_{n}-T
    $$
    换言之,我们即要检验是否存在$S_{i}<S_{n}-T$且$forall ile jle n,S_{j}<S_{n}-T+C$,显然后者具有单调性,通过线段树可以确定$i$的下限,然后求区间最小值即可

    时间复杂度为$o(nlog^{2}n)$,可以通过

     1 #include<bits/stdc++.h>
     2 #include"candies.h"
     3 using namespace std;
     4 #define N 200005
     5 #define ll long long
     6 #define L (k<<1)
     7 #define R (L+1)
     8 #define mid (l+r>>1)
     9 vector<int>ans,Add[N],Dec[N];
    10 int n,m;
    11 ll tag[N<<2],mx[N<<2],mn[N<<2];
    12 void upd(int k,ll x){
    13     tag[k]+=x;
    14     mx[k]+=x;
    15     mn[k]+=x;
    16 }
    17 void up(int k){
    18     mx[k]=max(mx[L],mx[R]);
    19     mn[k]=min(mn[L],mn[R]);
    20 }
    21 void down(int k){
    22     upd(L,tag[k]);
    23     upd(R,tag[k]);
    24     tag[k]=0;
    25 }
    26 void update(int k,int l,int r,int x,int y,int z){
    27     if ((l>y)||(x>r))return;
    28     if ((x<=l)&&(r<=y)){
    29         upd(k,z);
    30         return;
    31     }
    32     down(k);
    33     update(L,l,mid,x,y,z);
    34     update(R,mid+1,r,x,y,z);
    35     up(k);
    36 }
    37 ll query(int k,int l,int r,int x,int y){
    38     if ((l>y)||(x>r))return 2e15;
    39     if ((x<=l)&&(r<=y))return mn[k];
    40     down(k);
    41     return min(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
    42 }
    43 int find(int k,int l,int r,ll x){
    44     if (mx[k]<x)return -1;
    45     if (l==r)return l;
    46     down(k);
    47     int ans=find(R,mid+1,r,x);
    48     if (ans>=0)return ans;
    49     return find(L,l,mid,x);
    50 }
    51 int query(int k){
    52     int l=0,r=k;
    53     ll S=query(1,0,m,m,m);
    54     while (l<r){
    55         int x=find(1,0,m,S-mid+k);
    56         if (query(1,0,m,x+1,m)>=S-mid)r=mid;
    57         else l=mid+1;
    58     }
    59     return l;
    60 }
    61 vector<int> distribute_candies(vector<int>c,vector<int>l,vector<int>r,vector<int>v){
    62     n=c.size(),m=l.size();
    63     for(int i=0;i<m;i++){
    64         Add[l[i]].push_back(i);
    65         Dec[r[i]].push_back(i);
    66     }
    67     for(int i=0;i<n;i++){
    68         for(int j=0;j<Add[i].size();j++)update(1,0,m,Add[i][j]+1,m,v[Add[i][j]]);
    69         ans.push_back(query(c[i]));
    70         for(int j=0;j<Dec[i].size();j++)update(1,0,m,Dec[i][j]+1,m,-v[Dec[i][j]]);
    71     }
    72     return ans;
    73 }
    View Code

     做法2

    仍然离线+差分,考虑递归处理$f(C,[a_{1},a_{2},...,a_{n}],x)$的值($x$指操作前的值,初始为0)

    令$sum_{i}=sum_{j=1}^{i}a_{j}$,$mx$为$sum_{i}$的最大值(包括$sum_{0}$),$mn$为最小值,对其分类讨论:

    1.若$x+mxle C$或$x+mnge 0$,即没有上限或下限,与之前的$g$类似

    2.注意到$C-mx<x<-mn$,也即$mx-mn>C$,则$f(C,a_{i},0)=f(C,a_{i},1)=...=f(C,a_{i},C)$

    由此,可以递归处理,当右子树$mx-mn>C$显然就不用递归左子树了,否则递归左子树后右子树的结果可以直接$o(1)$求出

    时间复杂度为$o(nlog n)$,可以通过

  • 相关阅读:
    iOS CALayer 学习(2)
    iOS CALayer 学习(1)
    iOS 绘画学习(5)
    iOS 绘画学习(4)
    果冻视图制作教程
    15个名不见经传的Unix命令
    WEB服务器2--IIS架构(转)
    WEB服务器1--开篇
    HTTP协议5之代理--转
    HTTP协议4之缓存--转
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15001610.html
Copyright © 2020-2023  润新知