[线段树] Jzoj P5232 带权排序

Description

 

Input

输入文件名为sort.in。
第一行包含一个整数n。
接下来n行,每行三个整数si,li,ri,表示Ai的值为[li,ri] 中的随机整数。

Output

输出文件名为sort.out。
输出一个整数,表示答案。
 

Sample Input

输入1:
4
1 2 3
4 4 6
2 0 5
3 2 6

输入2:
10
53736 68 512
82493 870 920
77300 206 576
63900 4 565
68675 0 488
13610 4 922
57472 614 825
37474 394 970
51896 398 766
77136 656 723

Sample Output

输出1:
650000033

输出2:
743178372
 

Data Constraint

对于20%的数据,n<=6,0<=li<=ri<=15
对于40%的数据,n<=10,0<=li<=ri<=20
对于60%的数据,0<=li<=ri<=1000
对于100%的数据,n<=10^5,0<=li<=ri<=10^9,0<=si<=10^9

题解

  • 现在考虑如何求这个东东,可以发现pi的期望其实就是有多少人排在i前
  • 那么它对i后的点j选在[0...l-1]是没有贡献的,若在[l...r]中,贡献就是x-l[i]+1/r[i]-l[i]+1,若在[r...inf]中,贡献就是1
  • 每个贡献其实就是在平面直角坐标系中,就是三段线段,这三段线段其实都是就是一个等差数列
  • 那我们就可以考虑在线段树里加上一条直线,维护线段的首项,末项和公差
  • 然后正反做一遍,就好了

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define ll long long
 5 using namespace std;
 6 const ll mo=1e9+7,N=100010,inf=1e9;
 7 struct edge{ll l,r,v,x,y;}tree[N*60];
 8 ll a[N],l[N],r[N],k[N],n,cnt,d,o,ans;
 9 ll ksm(ll a,ll b) 
10 {
11     ll r=1;
12     for (;b;b>>=1,a=a*a%mo) if (b&1) r=r*a%mo; 
13     return r;
14 }
15 void work(ll &d,ll l,ll r,ll L,ll R)
16 {
17     if (!d) d=++cnt;
18     (tree[d].x+=L)%=mo,(tree[d].y+=R)%=mo,(tree[d].v+=(r-l+1)*R)%=mo;
19     if ((l+r)&1) o=(r-l+1)/2*(r+l)%mo; else o=(r+l)/2*(r-l+1)%mo;
20     (tree[d].v+=o*L)%=mo;
21 }
22 void down(ll d,ll l,ll r)
23 {
24     if (tree[d].x||tree[d].y)
25     {
26         ll mid=l+r>>1;
27         work(tree[d].l,l,mid,tree[d].x,tree[d].y),work(tree[d].r,mid+1,r,tree[d].x,tree[d].y);
28         tree[d].x=tree[d].y=0;
29     }
30 }
31 void insert(ll &d,ll l,ll r,ll L,ll R,ll x,ll y)
32 {
33     if (R<l||L>r) return;
34     if (!d) d=++cnt;
35     if (L<=l&&r<=R) work(d,l,r,x,y);
36     else 
37     {
38         ll mid=l+r>>1; down(d,l,r);
39         insert(tree[d].l,l,mid,L,R,x,y),insert(tree[d].r,mid+1,r,L,R,x,y);
40         tree[d].v=(tree[tree[d].l].v+tree[tree[d].r].v)%mo;
41     }
42 }
43 ll Query(ll d,ll l,ll r,ll L,ll R)
44 {
45     if (R<l||L>r) return 0;
46     if (L<=l&&r<=R) return tree[d].v;
47     ll mid=l+r>>1; down(d,l,r);
48     return (Query(tree[d].l,l,mid,L,R)+Query(tree[d].r,mid+1,r,L,R))%mo;
49 }
50 int main()
51 {
52     freopen("sort.in","r",stdin),freopen("sort.out","w",stdout);
53     scanf("%lld",&n);
54     for (ll i=1;i<=n;i++) scanf("%lld%lld%lld",&a[i],&l[i],&r[i]);
55     for (ll i=1;i<=n;i++)
56     {
57         ll ny=ksm(r[i]-l[i]+1,mo-2);
58         k[i]=Query(d,0,inf,l[i],r[i])*ny%mo;
59         insert(d,0,inf,r[i]+1,inf,0,1),insert(d,0,inf,l[i],r[i],ny,(mo-(l[i]-1)*ny%mo)%mo);
60     }
61     d=0;
62     for (ll i=1;i<=cnt;i++) tree[i].x=tree[i].y=tree[i].v=tree[i].l=tree[i].r=0;
63     cnt=0;
64     for (ll i=n;i;i--)
65     {
66         ll ny=ksm(r[i]-l[i]+1,mo-2);
67         (k[i]+=Query(d,0,inf,l[i],r[i])*ny%mo)%=mo;
68         insert(d,0,inf,r[i]+1,inf,0,1),insert(d,0,inf,l[i],r[i],ny,(mo-l[i]*ny%mo)%mo);
69     }
70     for (ll i=1;i<=n;i++) ans=(ans+(k[i]+1)*a[i])%mo;
71     printf("%lld",ans);
72 }
原文地址:https://www.cnblogs.com/Comfortable/p/10311390.html