【NOIP2017模拟A组模拟8.5】带权排序

来源:互联网 发布:工业机器人网络培训 编辑:程序博客网 时间:2024/06/05 19:51

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

Solution

这些题脑洞怎么这么大

ans=E[f(A)]=E[i=1ns[i]p[i]]=i=1ns[i]E[p[i]]

考虑求E[p[i]]
可以知道,位置i的取值是l[i]~r[i]
假设取x
那么考虑一个位置j(j<i)
假设r[j]<=x,那么j对i取x时的贡献为1(这些贡献都要/(r[i]l[i]+1)这里省略)
假设l[j]>x,那么j对i取x时的贡献为0
假设l[j]<=x<=r[j],那么j对i取x时的贡献为xl[j]+1r[j]l[j]+1

考虑一个位置j(j>i)
假设r[j]<x,那么j对i取x时的贡献为1(这些贡献都要/(r[i]l[i]+1)这里省略)
假设l[j]>x,那么j对i取x时的贡献为0
假设l[j]<x<r[j],那么j对i取x时的贡献为xl[j]r[j]l[j]+1


如果通过枚举x的方法来做,可以得60分
再发现一些东西
考虑位置j对位置i的贡献(j<i)反过来同理
再看i取x时
贡献为xl[j]+1r[j]l[j]+1
那么i取每个数的贡献就是r[i]x=l[i]xl[j]+1r[j]l[j]+1
在一个数轴上,如果将l[j]~r[j]的地方每个位置x加上xl[j]+1r[j]l[j]+1,就是加上一个等差数列,在r[j]+1~n的每个位置+1,那么j对i的贡献是不是就是数轴上l[i]~r[i]的和
这个数轴可以通过线段树来维护,等差数列也是可以合并的
因为等差数列一定加在整个区间上,所以等差数列只需维护初始值(首项)s和公差t
那么两个等差数列s1t1和s2t2合并后,初始值就是s1+s2,公差就是t1+t2

Code

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(ll i=a;i<=b;i++)#define fd(i,a,b) for(ll i=a;i>=b;i--)#define N 1010000#define ll long long#define mo 1000000007using namespace std;int l[N],r[N],s[N],n,mx=0,tot=1;ll ans,p[N],ny2;struct node{    int l,r;    ll sum,s,t;}t[N*10];ll mi(ll a,ll b){    if(b==0) return 1;    if(b==1) return a;    ll k=mi(a,b/2);    k=(k*k)%mo;    if(b%2==1) k=(k*a)%mo;    return k;}ll calc(ll a,ll b,ll c){    return (((((b+b+(a-1)*c)%mo)*a)%mo)*ny2)%mo;}void down(int v,ll i,ll j,ll m){    t[v].l=t[v].l==0?++tot:t[v].l;    t[v].r=t[v].r==0?++tot:t[v].r;    (t[t[v].l].sum+=calc(m-i+1,t[v].s,t[v].t))%=mo;    (t[t[v].r].sum+=calc(j-m,(t[v].s+(m-i+1)*t[v].t)%mo,t[v].t))%=mo;    (t[t[v].l].s+=t[v].s)%=mo;(t[t[v].l].t+=t[v].t)%=mo;    (t[t[v].r].s+=(t[v].s+(m-i+1)*t[v].t)%mo)%=mo;(t[t[v].r].t+=t[v].t)%=mo;    t[v].s=t[v].t=0;}ll get(int v,int i,int j,ll l,ll r)                                                                                                                                                                             {    if(v==0) return 0;    if(i==l&&j==r) return t[v].sum;    ll m=(i+j)/2;down(v,i,j,m);    if(r<=m) return get(t[v].l,i,m,l,r);    else if(l>m) return get(t[v].r,m+1,j,l,r);         else return (get(t[v].l,i,m,l,m)+get(t[v].r,m+1,j,m+1,r))%mo;}void ins(int v,int i,int j,ll l,ll r,ll z,ll e){    if(i==l&&j==r)    {        (t[v].sum+=calc(r-l+1,z,e))%=mo;        (t[v].s+=z)%=mo;(t[v].t+=e)%=mo;        return;    }    ll m=(i+j)/2;down(v,i,j,m);    if(r<=m) ins(t[v].l,i,m,l,r,z,e);    else if(l>m) ins(t[v].r,m+1,j,l,r,z,e);         else ins(t[v].l,i,m,l,m,z,e),ins(t[v].r,m+1,j,m+1,r,(z+(m-l+1)*e)%mo,e);    t[v].sum=(t[t[v].l].sum+t[t[v].r].sum)%mo;   }void read(int &x){    char ch=getchar();    for(;ch<'0'||ch>'9';ch=getchar());    x=0;    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-48;}int main(){    freopen("sort.in","r",stdin);    freopen("sort.out","w",stdout);    ny2=mi(2,mo-2);    scanf("%d",&n);    fo(i,1,n) read(s[i]),read(l[i]),read(r[i]),l[i]++,r[i]++,mx=max(mx,r[i]);    mx++;    fo(i,1,n)    {        ll ny=mi(r[i]-l[i]+1,mo-2);        p[i]=1+get(1,1,mx,l[i],r[i])*ny%mo;        ins(1,1,mx,l[i],r[i],ny,ny);        ins(1,1,mx,r[i]+1,mx,1,0);    }    memset(t,0,sizeof(t));    tot=1;    fd(i,n,1)    {        ll ny=mi(r[i]-l[i]+1,mo-2);        p[i]=(p[i]+get(1,1,mx,l[i],r[i])*ny)%mo;        if(l[i]<r[i]) ins(1,1,mx,l[i]+1,r[i],ny,ny);        ins(1,1,mx,r[i]+1,mx,1,0);    }    fo(i,1,n) (ans+=(p[i]*(ll)s[i])%mo)%=mo;    printf("%lld",ans);}
阅读全文
1 0
原创粉丝点击