• CF1452E Two Editorials (思维题,暴力+差分)


    题目描述:

    给你m个位于[1,n]的区间p,现在有长度为K的区间b和c。设对于区间$p[i]$,定义$a[i]$为$p[i]$分别与b,c相交长度的较大值,现在问区间b和c位于何处时,$sum p_{i}$最大,输出这个最大值,n,m,K<=2000

    好题目,dkr yyds!

    暴力怎么搞?暴力枚举b,c的位置,然后O(n)计算,总时间$O(n^{3})$

    考虑优化这个暴力,每次只暴力枚举b的位置,并统计所有pi与b相交的长度之和。如果c和pi相交比b大,那么会产生额外贡献,这个额外贡献的值就是c与pi相交长度减掉b与pi相交的长度

    考虑每次都把c区间从左到右一格一格挪,挪进第i个区间的长度超过ai时,开始产生贡献,每超过一格,贡献就+1。每挪一次,我们就在c右端点的位置打上+1标记

    然而挪多了可能不再增加新贡献,就停止打+1。

    挪出去了还会减少贡献,开始打-1,直到贡献减成0,停止打-1

    实际操作中也不必真的挪c,也不用记录什么时候减到0,推位置就可以了

    怎么推位置呢?分K和xi长度大小讨论,推吧推吧就出来了,细节比较多

    +1和-1这些标记都是连续的,差分就行。那么求两次前缀和即可

    总时间$O(n^{2})$

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define N1 2005
     5 #define ll long long
     6 #define mod 998244353
     7 using namespace std;
     8 
     9 int n,m,K;
    10 int l[N1],r[N1],a[N1];
    11 int adds[N1],addt[N1],subs[N1],subt[N1];
    12 ll sum1[N1],sum2[N1];
    13 
    14 void clr()
    15 {
    16     memset(adds,0,sizeof(adds));
    17     memset(addt,0,sizeof(addt));
    18     memset(subs,0,sizeof(subs));
    19     memset(subt,0,sizeof(subt));
    20     memset(sum1,0,sizeof(sum1));
    21     memset(sum2,0,sizeof(sum2));
    22 }
    23 
    24 int main()
    25 {
    26     freopen("a.txt","r",stdin);
    27     scanf("%d%d%d",&n,&m,&K);
    28     for(int i=1;i<=m;i++) scanf("%d%d",&l[i],&r[i]);
    29     ll ANS=0,ans=0;
    30     for(int i=1;i+K-1<=n;i++)//l~l+K-1
    31     {
    32         int L=i,R=i+K-1; ans=0;
    33         for(int j=1;j<=m;j++)
    34         {
    35             a[j]=max(0,min(r[j],i+K-1)-max(l[j],i)+1);
    36             ans+=a[j];
    37         }
    38         for(int j=1;j<=m;j++)
    39         {
    40             ++adds[l[j]+a[j]];
    41             ++addt[min(r[j]+1,min(l[j]+K,n+1))]; //addt: +1的结束位置 +1
    42             ++subs[max(min(l[j]+K,n+1),r[j]+1)]; //subs: -1start_point 
    43             ++subt[min(r[j]-a[j]+1+K,n+1)]; //subt: -1end_point +1
    44         }
    45         ll tmp=0;
    46         for(int j=1;j<=n;j++) sum1[j]+=sum1[j-1]+adds[j]-addt[j]-subs[j]+subt[j];
    47         for(int j=1;j<=n;j++) sum2[j]=sum2[j-1]+sum1[j], tmp=max(tmp,sum2[j]);
    48         ANS=max(ANS,ans+tmp);
    49         clr();
    50     }
    51     printf("%lld
    ",ANS);
    52     return 0;
    53 }
  • 相关阅读:
    sell -- js, 字符串去重,找到字符串中出现最多次数的字符,且输出多少次
    网络连接不了!
    sell -- js过滤敏感词
    动态绑定HTML
    web前端学习之HTML CSS/javascript之一
    web前端性能优化
    浅谈大型web系统架构
    应用越来越广泛的css伪类
    css3火焰文字样式代码
    7种html5css3网页图片展示特效代码
  • 原文地址:https://www.cnblogs.com/guapisolo/p/14010459.html
Copyright © 2020-2023  润新知