高速公路题解

Posted lsoi_ljk123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高速公路题解相关的知识,希望对你有一定的参考价值。

高速公路题解

我们看一看题,就知道概率是是区间内所有线段的权值和/线段个数。
那么,我们需要动态维护区间的数据结构,
很容易想到线段树,
考虑,如何将两个区间合并:

注:以下线段树上的每个点的\\(sum\\)在代码中为\\(sum2\\),仅为方便理解。

不妨设每个区间\\([l,r]\\)内的所有线段权值和为\\(w\\)\\([l,r]\\)的线段权值为\\(sum\\),左端点为\\(l\\)的所有线段权值和为\\(lw\\),右端点为\\(r\\)的所有线段的权值和为\\(rw\\),懒标记为\\(lazy\\),区间长度为\\(lenx=r-l+1\\)
假如此区间为\\(x\\),左区间为\\(lc\\),右区间为\\(rc\\):
\\(x\\)\\(w\\)除去由\\(lc,rc\\)各自区间内部的\\(w\\)外,
还由经过左右两个区间的线段构成,
画图理解一下:

然后第二个问题来了,如何维护\\(lw,rw\\)?

至于\\(sum,lazy\\)还用说吗? 线段树模板啊!

xd pushup(xd u,xd v){
   xd ans; int len=u.lenx+v.lenx;
   ans.lw=u.lw+v.lw+v.lenx*u.sum2,ans.rw=u.rw+v.rw+u.lenx*v.sum2,ans.lazy=0;
   ans.w=u.w+v.w+u.lenx*v.lw+v.lenx*u.rw,ans.sum2=u.sum2+v.sum2,ans.lenx=len;
   return ans;
}

再想想下传标记:
对于每个\\(x\\)\\(w\\),所有线段都加了线段长度\\(*lazy[x]\\);
\\(sum[len]\\)为长度为\\(len\\)的区间所有线段的长度和。
\\(l-1\\)每增加一个长度,则每个长度的线段都有一个,即为:\\(\\sum_{i=1}^{l}=/frac{(l+1)*l}{2}\\)
递推即可。

for(ll i=1;i<=n;++i) sum[i]=sum[i-1]+i*(i+1)/2;

所以:

t[lc].w+=sum[t[lc].lenx]*t[x].lazy,t[rc].w+=sum[t[rc].lenx]*t[x].lazy;

对于\\(lw\\)\\(rw\\)
区间\\([l,r]\\)长度在[1,r-l+1]的线段都有一种:

t[lc].lw+=(t[lc].lenx+1)*t[lc].lenx/2*t[x].lazy,t[lc].rw+=(t[lc].lenx+1)*t[lc].lenx/2*t[x].lazy;
t[rc].lw+=(t[rc].lenx+1)*t[rc].lenx/2*t[x].lazy,t[rc].rw+=(t[rc].lenx+1)*t[rc].lenx/2*t[x].lazy;

\\(sum,lenx,lazy\\)的下传也不讲了。

#include<bits/stdc++.h>
#define ll long long 
#define lc x<<1
#define rc x<<1|1
using namespace std;
const int N=1e5+6;
int n,m,t3;
ll sum[N],o,p,q,t1,t2;
char c[12];
struct xd{ll w,lazy,lw,rw,lenx,sum2;}t[N<<2];
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<\'0\'||ch>\'9\'){if(ch==\'-\') F=-1; ch=getchar();}
   while(ch>=\'0\'&&ch<=\'9\') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
ll gcd(ll u,ll v){return u%v==0?v:gcd(v,u%v);}
void pushdown(int x){
     if(t[x].lazy){
        t[lc].lazy+=t[x].lazy,t[rc].lazy+=t[x].lazy;
        t[lc].w+=sum[t[lc].lenx]*t[x].lazy,t[rc].w+=sum[t[rc].lenx]*t[x].lazy;
        t[lc].lw+=(t[lc].lenx+1)*t[lc].lenx/2*t[x].lazy,t[lc].rw+=(t[lc].lenx+1)*t[lc].lenx/2*t[x].lazy;
        t[rc].lw+=(t[rc].lenx+1)*t[rc].lenx/2*t[x].lazy,t[rc].rw+=(t[rc].lenx+1)*t[rc].lenx/2*t[x].lazy;
        t[lc].sum2+=t[lc].lenx*t[x].lazy,t[rc].sum2+=t[rc].lenx*t[x].lazy;
        t[x].lazy=0;
     }
}
xd pushup(xd u,xd v){
   xd ans; int len=u.lenx+v.lenx;
   ans.lw=u.lw+v.lw+v.lenx*u.sum2,ans.rw=u.rw+v.rw+u.lenx*v.sum2,ans.lazy=0;
   ans.w=u.w+v.w+u.lenx*v.lw+v.lenx*u.rw,ans.sum2=u.sum2+v.sum2,ans.lenx=len;
   return ans;
}
void build(int l,int r,int x){
     t[x].lenx=r-l+1;
     if(l==r) return;
     int mid=l+r>>1;
     build(l,mid,lc),build(mid+1,r,rc);
} 
void update(ll l,ll r,int p,int q,int x,ll y){
     if(p<=l&&r<=q){t[x].lazy+=y,t[x].w+=sum[r-l+1]*y,t[x].lw+=(r-l+1)*(r-l+2)/2*y,t[x].rw+=(r-l+1)*(r-l+2)/2*y,t[x].sum2+=(r-l+1)*y;  return;}
     pushdown(x); int mid=l+r>>1;
     if(p<=mid) update(l,mid,p,q,lc,y);
     if(q>mid) update(mid+1,r,p,q,rc,y);
     t[x]=pushup(t[lc],t[rc]);
}
xd query(int l,int r,int p,int q,int x){
   if(p<=l&&r<=q){return t[x];}
   pushdown(x); int mid=l+r>>1; xd ans;
   if(q<=mid) ans=query(l,mid,p,q,lc);
   else if(p>mid) ans=query(mid+1,r,p,q,rc);
   else ans=pushup(query(l,mid,p,q,lc),query(mid+1,r,p,q,rc));
   return ans;
}
int main(){
    n=read(),m=read(),--n;
    for(ll i=1;i<=n;++i) sum[i]=sum[i-1]+i*(i+1)/2;
    build(1,n,1);
    for(int i=1;i<=m;++i){
        scanf("%s",c); t1=read(),t2=read()-1;
        if(c[0]==\'C\') t3=read(),update(1,n,t1,t2,1,t3);
        else{
            o=(t2-t1+1)*(t2-t1+2)/2,p=query(1,n,t1,t2,1).w;
            if(p) q=gcd(o,p),o/=q,p/=q;
            else o=1;
            printf("%lld/%lld\\n",p,o);
        }
    }
    return 0;
}  

以上是关于高速公路题解的主要内容,如果未能解决你的问题,请参考以下文章

题解Luogu P2221 [HAOI2012]高速公路

神奇脑洞题解——HAOI2012高速公路(数学期望,线段树)

CF498D:Traffic Jams in the Land——题解

luogu P1111 公路修建 题解

题解报告:hdu 1233 还是畅通工程

CCF系列题解--2016年9月第四题 交通规划