1. 程式人生 > >Codeforces Round #435 (Div. 2) E. Mahmoud and Ehab and the function(預處理+二分)

Codeforces Round #435 (Div. 2) E. Mahmoud and Ehab and the function(預處理+二分)

class [1] can 行處理 long 個數 分享 amp abs

題目鏈接:點我點我

題意:公式:技術分享,給出n個數,從a[1]到a[n],和m個數(b數組),然後從b數組裏挑出連續的n個數(也就m-n+1中選擇),按公式計算,使得f最小,

還有q次對a數組的操作(某個區間增加值,減少值),求出最小值。

題解:顯然對a數組的處理非常簡單,一開始確定一定值,然後update的時候,判斷一下奇偶性質就可以直接加了(前一項正後一項一定是負的,可以抵消)。

然後就是b數組的處理了,一開始沒處理好,一直在這邊卡超時。先把b數組一項一項正負不同的加進去,然後再進行處理,得到c數組(代表b數組各種情況下的值),

然後排序二分一下。

這道題目感覺自己收獲非常大,顛覆了我很多錯誤的想法:

1.二分函數lower_bound(c+1,c+c.size(),goal)-c中間那裏加上的是數組長度而不是和sort一樣是“地址”

2.upper_bound()函數是第一個大於val的位置(一直以為是小於等於val的最後一個位置,(尷尬 。。。)

 1 #include <bits/stdc++.h>
 2 using namespace std; 
 3 
 4 typedef long long LL;
 5 LL INF=1e18;
 6 const int N=1e5+111;
 7 LL a[N],b[N],c[N];
8 9 int main(){ 10 LL n,m,q,pos,sum=0,tmp; 11 cin>>n>>m>>q; 12 for(int i=1;i<=n;i++){ 13 scanf("%lld",&a[i]); 14 i%2==1 ? sum+=a[i] : sum-=a[i]; 15 } 16 for(int i=1;i<=m;i++){ 17 scanf("%lld",&tmp); 18 if(i%2
==0) tmp*=-1; 19 b[i]=b[i-1]+tmp; 20 } 21 for(int i=1;i<=m-n+1;i++){ 22 if(i%2) c[i]=(b[i-1]-b[i+n-1]); 23 else c[i]=(b[i+n-1]-b[i-1]); 24 } 25 sort(c+1,c+1+m-n+1); 26 LL ans=INF,x,y,z; 27 pos=lower_bound(c+1,c+m-n+1,-sum)-c; 28 if(pos==1) 29 ans=abs(sum+c[pos]); 30 else 31 ans=min(abs(sum+c[pos]),abs(sum+c[pos-1])); 32 printf("%lld\n",ans); 33 for(int k=1;k<=q;k++){ 34 ans=INF; 35 scanf("%lld %lld %lld",&x,&y,&z); 36 if(y==x) {y%2==1 ? sum+=z : sum-=z;} 37 else if((y-x+1)%2) {x%2==1 ? sum+=z : sum-=z;} 38 pos=lower_bound(c+1,c+m-n+1,-sum)-c; 39 if(pos==1) 40 ans=abs(sum+c[pos]); 41 else 42 ans=min(abs(sum+c[pos]),abs(sum+c[pos-1])); 43 printf("%lld\n",ans); 44 } 45 return 0; 46 }

Codeforces Round #435 (Div. 2) E. Mahmoud and Ehab and the function(預處理+二分)