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 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章