[NOIP2018校模擬賽]T1聚會 party
阿新 • • 發佈:2018-10-02
get P20 mem .net 家庭 tchar 我們 圖片 mes
題目鏈接:
聚會
分析:
設每個點到1號點的距離為dist_{i},每個點的權值為x_{i},目標點到1號點的距離為dist,權值為x,那麽對於每一次查詢,我們討論三種情況:
① 目標家庭在區間左邊(x<=l)
如圖所示
這種情況下
ans=sum((dist_{i}-dist)*x_{i])
=sum(dist_{i]*x_{i}) - dist*sum(x_{i})
②目標家庭在區間右邊(x>=r)
容易同理得到 ans= dist*sum(x_{i})-sum(dist_{i]*x_{i})
③目標家庭在區間中間(l<x<r)
將區間從目標家庭處分開,分別求左右子區間的ans1,ans2,過程同①,②
為了降低時間復雜度,每個點到1號點的距離,每個點的權值,以及前兩項的乘積都用前綴和來存儲,於是我們維護三個前綴和數組——代碼中分別是dist,b,p,這樣對於每次查詢的時間復雜度是O(1)的,總時間復雜度為O(N)。
被坑到的點:
相減的時候可能出現負值,對應的余數也會變成負值,這時候加一個特判
if(ans<0)ans+=mod;
即可。(不加會見祖宗你信嗎)
代碼如下:
#include<bits/stdc++.h> #define frog 19260817 using namespace std; inline long long read(){ int cnt=0,f=1;char c; c=getchar(); while(!isdigit(c)){if(c==‘-‘)f=-1;c=getchar();} while(isdigit(c)){cnt=cnt*10+c-‘0‘;c=getchar();} return cnt*f; } long long n,m,dist[200005],x=0,a,l,r; long long p[200005],b[200005]; long long ans; int main(){ n=read();m=read(); memset(dist,0,sizeof(dist)); memset(p,0,sizeof(p)); memset(b,0,sizeof(b)); for(register int i=2;i<=n;i++){ x=read(); dist[i]=(x+dist[i-1])%frog; } for(register int i=1;i<=n;i++){ x=read(); b[i]=(x+b[i-1])%frog; p[i]=(p[i-1]+x*dist[i])%frog; } for(register int i=1;i<=m;i++){ a=read();l=read();r=read(); if(a<=l){ long long t1=(p[r]-p[l-1])%frog; long long t2=((b[r]-b[l-1])*dist[a])%frog; ans=(t1-t2)%frog; } if(a>=r){ long long t1=(p[r]-p[l-1])%frog; long long t2=((b[r]-b[l-1])*dist[a])%frog; ans=(t2-t1)%frog; } if(l<a&&a<r){ long long t1=(p[a]-p[l-1])%frog; long long t2=((b[a]-b[l-1])*dist[a])%frog; long long t3=(p[r]-p[a])%frog; long long t4=((b[r]-b[a])*dist[a])%frog; ans=((t2-t1+t3-t4)%frog)%frog; } if(ans<0)ans+=frog; printf("%lld\n",ans); } return 0; }
[NOIP2018校模擬賽]T1聚會 party