1. 程式人生 > 實用技巧 >線段樹(種樹)

線段樹(種樹)

2017種樹

題目描述

2017共有N棵樹從0到N-1標號。現要把這些樹種在一條直線上,第i棵樹的種植位置X[i]如下確定:

X[0] = X[0] MOD L;

X[i] = (X[i-1]*A+B) MOD L。

每棵樹種植的費用,是所有標號比它小的樹與它的距離之和。2017請你計算各棵樹的費用之積,最後對1000000007取餘。

輸入格式

共五行:

第一行為N

第二行為L

第三行為X[0]

第四行為A

第五行為B

輸出格式

總費用

樣例

樣例輸入

5
10
3
1
1

樣例輸出

180

樣例解釋:

5棵樹的位置分別為: 3, 4, 5, 6, 7.

費用分別為: 1, 3, 6, 10. (從第一棵樹開始)

總費用為: 1 × 3 × 6 × 10 = 180.

資料範圍與提示

10%的資料:N<=10;

60%的資料:N<=2×10^5;

100%的資料:N,L<=200000; X[0] ,A, B<=10^9.

思路:

思路:用線段樹維護的數x小的個數以及比x(第i個數的位置)小的數的和,比x大的樹的個數以及比x大的數的和,x的費==(x×比x小的數的個數-比x小的數的和)+(比x大的數的和-x×比x大的數的個數)。

 1 #include<cstdio>
 2 const int maxn=200000
+10,mod=1000000007; 3 int tree[maxn<<2],cnt[maxn<<2]; 4 int n,l,xx,a,b; 5 int ans=1; 6 void Build(int rt,int l,int r){ 7 if(l==xx&&r==xx){ 8 tree[rt]+=xx; 9 cnt[rt]++; 10 return ; 11 } 12 int mid=(l+r)>>1; 13 if(xx<=mid) Build(rt<<1
,l,mid); 14 else Build(rt<<1|1,mid+1,r); 15 tree[rt]=(tree[rt<<1]+tree[rt<<1|1])%mod; 16 cnt[rt]=cnt[rt<<1]+cnt[rt<<1|1]; 17 } 18 int query(int rt,int l,int r,int s,int t){ 19 if(s<l) s=l; 20 if(t>r) t=r; 21 if(s==l&&t==r){ 22 return tree[rt]; 23 } 24 int mid=(l+r)>>1; 25 if(t<=mid) return query(rt<<1,l,mid,s,t)%mod; 26 else if(s>mid) return query(rt<<1|1,mid+1,r,s,t)%mod; 27 else return (query(rt<<1,l,mid,s,t)+query(rt<<1|1,mid+1,r,s,t))%mod; 28 } 29 int query1(int rt,int l,int r,int s,int t){ 30 if(s<l) s=l; 31 if(t>r) t=r; 32 if(s==l&&t==r) return cnt[rt]; 33 int mid=(l+r)>>1; 34 if(t<=mid) return query1(rt<<1,l,mid,s,t)%mod; 35 else if(s>mid) return query1(rt<<1|1,mid+1,r,s,t)%mod; 36 else return (query1(rt<<1,l,mid,s,t)+query1(rt<<1|1,mid+1,r,s,t))%mod; 37 } 38 void Modify(int rt,int l,int r,int w){ 39 if(l==w&&r==w){ 40 tree[rt]+=w; 41 cnt[rt]++; 42 return ; 43 } 44 int mid=(l+r)>>1; 45 if(w<=mid) Modify(rt<<1,l,mid,w); 46 else Modify(rt<<1|1,mid+1,r,w); 47 tree[rt]=(tree[rt<<1]+tree[rt<<1|1])%mod; 48 cnt[rt]=cnt[rt<<1]+cnt[rt<<1|1]; 49 } 50 void solve(int x){ 51 int Min_sum=query(1,0,l-1,0,x); 52 int Min_cnt=query1(1,0,l-1,0,x); 53 int Max_sum=query(1,0,l-1,x,l-1); 54 int Max_cnt=query1(1,0,l-1,x,l-1); 55 int sum=((Min_cnt*x)%mod-Min_sum%mod+Max_sum%mod-(Max_cnt*x)%mod)%mod; 56 ans=(ans*sum)%mod; 57 Modify(1,0,l-1,x); 58 } 59 int main(){ 60 scanf("%d%d%d%d%d",&n,&l,&xx,&a,&b); 61 xx=xx%l; 62 Build(1,0,l-1); 63 for(int i=1;i<n;i++){ 64 int x; 65 x=(xx*a+b)%mod; 66 solve(x); 67 xx=x; 68 } 69 printf("%d\n",ans); 70 return 0; 71 }
View Code