1. 程式人生 > >2018.10.02 NOIP模擬 聚會(字首和)

2018.10.02 NOIP模擬 聚會(字首和)

描述

在成都的一條街道上,一共有 N戶人家,每個家庭有 Xi 個人,他們和諧的生活在 一起,作為全國和諧街道,他們經常會小範圍組織活動,每次活動會選擇一戶作為聚點, 並要求某些家庭參加,為了方便通知,村長每次邀請位置連續的家庭。因為每戶人數不 同,每個家庭之間有一定距離,村長希望你計算出每次邀請的家庭的移動代價。第 i個家 庭移動到家庭 jj的代價是:Xi∗dis(i,j) dis(i,j)表示i 到j的距離,村長一共安排了 m 次聚會,每次邀請[Li,Ri]的家庭參加

輸入

第一行兩個數表示 n,m 第二行 n-1 個數,第 i 個數表示第 i 個家庭與第 i+1 個家庭的距離 Di 第三行 n 個數,表示每個家庭的人數 Xi 之後 m 行每行三個數 x l r,表示查詢要把區間 [l,r]的家庭移動到 x 點的代價和

輸出

對於每個詢問輸出一個數表示答案,對 19260817 取模

樣例輸入

5 5 2 3 4 5 1 2 3 4 5 1 1 5 3 1 5 2 3 3 3 3 3 1 5 5

樣例輸出

125 72 9 0 70

提示

對於 30%的資料, n,m≤1000 對於另外 20%的資料,所有家庭間的距離都為 1 對於另外 20%的資料,所有家庭人數都為 1 對於 100%的資料 , n,m≤200000;Xi,Di <=2*10^9

今天的簽到題。 直接字首和處理一下就秒了。 然而考試的時候智障用線段樹維護被卡成了30分,交到OJ一測竟然有100? 搞得我都快生無可戀了。 如果用線段樹來做可以類比這道題的寫法,直接維護區間內所有點都搬到最左/右端點的花費。 程式碼:

#include<bits/stdc++.h>
#define mod 19260817
#define ll long long
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 200005
using namespace std;
inline ll read(){
	ll ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<
3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } int n,m; ll x[N],sum[N]; struct Node{int l,r,lp,rp;ll ls,rs;}T[N<<2]; inline Node operator+(Node a,Node b){ Node ret; ret.l=a.l,ret.r=b.r,ret.lp=a.lp,ret.rp=b.rp; ret.ls=(a.ls+b.ls+((sum[b.rp]-sum[b.lp-1])%mod+mod)%mod*((x[b.lp]-x[a.lp])%mod+mod)%mod)%mod; ret.rs=(b.rs+a.rs+((sum[a.rp]-sum[a.lp-1])%mod+mod)%mod*((x[b.rp]-x[a.rp])%mod+mod)%mod)%mod; return ret; } inline void build(int p,int l,int r){ T[p].l=l,T[p].r=r; if(l==r){T[p].lp=T[p].rp=l;return;} build(lc,l,mid),build(rc,mid+1,r),T[p]=T[lc]+T[rc]; } inline Node query(int p,int ql,int qr){ if(ql<=T[p].l&&T[p].r<=qr)return T[p]; if(qr<=mid)return query(lc,ql,qr); if(ql>mid)return query(rc,ql,qr); return query(lc,ql,mid)+query(rc,mid+1,qr); } int main(){ // freopen("party.in","r",stdin); // freopen("party.out","w",stdout); n=read(),m=read(); for(int i=2;i<=n;++i)x[i]=(x[i-1]+read())%mod; for(int i=1;i<=n;++i)sum[i]=(read()+sum[i-1])%mod; build(1,1,n); while(m--){ int op=read(),l=read(),r=read(); if(op<l){ Node tmp=query(1,l,r); printf("%lld\n",(tmp.ls+((x[l]-x[op])%mod+mod)%mod*((sum[r]-sum[l-1])%mod+mod)%mod)%mod); } else if(op>r){ Node tmp=query(1,l,r); printf("%lld\n",(tmp.rs+((x[op]-x[r])%mod+mod)%mod*((sum[r]-sum[l-1])%mod+mod)%mod)%mod); } else printf("%lld\n",(query(1,l,op).rs+query(1,op,r).ls)%mod); } return 0; }