码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2012]高速公路

时间:2018-02-03 13:24:29      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:long   logs   man   val   eps   strong   str   back   math   

题面在这里

题意

维护区间加操作+询问区间任选两不同点途中线段权值之和的期望

sol

一道假的期望题...
因为所有事件的发生概率都相同,所以答案就是所有方案的权值总和/总方案数
因为区间加法自然想到线段树,考虑将每条道路看作一个节点
那么对于区间l-r的路径(注意这里已经将道路看作节点,所以r--),可以计算第x条道路的贡献为
\((i-l+1)*(r-i+1)*val[i]\)(\(val[i]\)表示当前道路的权值大小)
那么我们要区间维护的就是这个东西
\[\sum_{r}^{i=l}{(i-l+1)*(r-i+1)*val[i]}\]
\[=\sum_{r}^{i=l}{(-i^2*va[i])}+(l+r)*\sum_{r}^{i=l}{(i*val[i])+(-l*r-l+r+1)*\sum_{r}^{i=l}val[i]}\]
分别维护\(\sum_{r}^{i=l}(i^2*val[i])\),\(\sum_{r}^{i=l}{(i*val[i])}\)\(\sum_{r}^{i=l}{val[i]}\),最后再除以\(((r-l+1)*(r-l+2)/2)\)即可

代码

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
const int mod=1e9+7;
const int N=100010;
const double eps=1e-10;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
il ll read(){
    RG ll data=0,w=1;RG char ch=getchar();
    while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar();
    if(ch==‘-‘)w=-1,ch=getchar();
    while(ch<=‘9‘&&ch>=‘0‘)data=data*10+ch-48,ch=getchar();
    return data*w;
}

int n,m;char ch;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
ll x[N],xx[N];
ll sum[N<<3],sumx[N<<3],sumxx[N<<3],lz[N<<3],cnt;
il void update(int i){
    sum[i]=sum[ls]+sum[rs];
    sumx[i]=sumx[ls]+sumx[rs];
    sumxx[i]=sumxx[ls]+sumxx[rs];
}

il void change(int i,int l,int r,ll v){
    sum[i]+=v*(r-(l-1));sumx[i]+=v*(x[r]-x[l-1]);
    sumxx[i]+=v*(xx[r]-xx[l-1]);lz[i]+=v;
}

il void pushdown(int i,int l,int r){
    if(!lz[i])return;
    change(ls,l,mid,lz[i]);change(rs,mid+1,r,lz[i]);
    lz[i]=0;
}

il void modify(int i,int l,int r,int x,int y,ll v){
    //区间修改
    if(x<=l&&r<=y){change(i,l,r,v);return;}
    pushdown(i,l,r);
    if(x<=mid)modify(ls,l,mid,x,y,v);
    if(mid+1<=y)modify(rs,mid+1,r,x,y,v);
    update(i);
}

il ll query_sum(int i,int l,int r,int x,int y){
    if(x<=l&&r<=y)return sum[i];
    RG ll s=0;pushdown(i,l,r);
    if(x<=mid)s+=query_sum(ls,l,mid,x,y);
    if(y>=mid+1)s+=query_sum(rs,mid+1,r,x,y);
    return s;
}
il ll query_sumx(int i,int l,int r,int x,int y){
    if(x<=l&&r<=y)return sumx[i];
    RG ll s=0;pushdown(i,l,r);
    if(x<=mid)s+=query_sumx(ls,l,mid,x,y);
    if(y>=mid+1)s+=query_sumx(rs,mid+1,r,x,y);
    return s;
}
il ll query_sumxx(int i,int l,int r,int x,int y){
    if(x<=l&&r<=y)return sumxx[i];
    RG ll s=0;pushdown(i,l,r);
    if(x<=mid)s+=query_sumxx(ls,l,mid,x,y);
    if(y>=mid+1)s+=query_sumxx(rs,mid+1,r,x,y);
    return s;
}

il void query(int l,int r){
    //按照推导公式解决询问操作
    RG ll ans1=query_sumxx(1,1,n-1,l,r)*(-1)+query_sumx(1,1,n-1,l,r)*(l+r)+query_sum(1,1,n-1,l,r)*(1ll*l*r*(-1)-l+r+1);
    RG ll ans2=1ll*(r-l+1)*(r-l+2)/2;
    RG ll g=gcd(ans1,ans2);
    printf("%lld/%lld\n",ans1/g,ans2/g);
}

int main()
{
    n=read();m=read();
    for(RG int i=1;i<n;i++){
        x[i]=x[i-1]+i;xx[i]=xx[i-1]+1ll*i*i;
    }
    for(RG int i=1,l,r;i<=m;i++){
        ch=0;while(ch!=‘C‘&&ch!=‘Q‘)ch=getchar();
        if(ch==‘C‘){
            l=read();r=read()-1;RG ll v=read();
            modify(1,1,n-1,l,r,v);
        }
        else{l=read();r=read()-1;query(l,r);}
    }
    return 0;
}

[HAOI2012]高速公路

标签:long   logs   man   val   eps   strong   str   back   math   

原文地址:https://www.cnblogs.com/cjfdf/p/8408573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!