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
这些题脑洞怎么这么大
考虑求 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时的贡献为 x−l[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时的贡献为
x−l[j]r[j]−l[j]+1
如果通过枚举x的方法来做,可以得60分
再发现一些东西
考虑位置j对位置i的贡献
(j<i)
反过来同理
再看i取x时
贡献为
x−l[j]+1r[j]−l[j]+1
那么i取每个数的贡献就是
∑r[i]x=l[i]x−l[j]+1r[j]−l[j]+1
在一个数轴上,如果将l[j]~r[j]的地方每个位置x加上
x−l[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 1000000007
using 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);
}