线段树(种树)
Posted hzoidj123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树(种树)相关的知识,希望对你有一定的参考价值。
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 ",ans); 70 return 0; 71 }
以上是关于线段树(种树)的主要内容,如果未能解决你的问题,请参考以下文章