zoukankan      html  css  js  c++  java
  • [线段树] 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 }
  • 相关阅读:
    HDU 1525
    kmp模板
    hdu 4616 Game(树形DP)
    hdu 4619 Warm up 2(并查集活用)
    hdu 4614 Vases and Flowers(线段树加二分查找)
    Codeforces 400D Dima and Bacteria(并查集最短路)
    poj 2823 Sliding Window (单调队列)
    hdu 2196 Computer(树形dp)
    hdu 4604 Deque
    最短路径
  • 原文地址:https://www.cnblogs.com/Comfortable/p/10311390.html
Copyright © 2011-2022 走看看