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\n",ANS);
52     return 0;
53 }

 

posted @ 2020-11-20 14:00  guapisolo  阅读(519)  评论(1编辑  收藏  举报