zoukankan      html  css  js  c++  java
  • [HAOI2012]高速公路

    题目描述

    Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站。

    Y901高速公路是一条由N-1段路以及N个收费站组成的东西向的链,我们按照由西向东的顺序将收费站依次编号为1~N,从收费站i行驶到i+1(或从i+1行驶到i)需要收取Vi的费用。高速路刚建成时所有的路段都是免费的。

    政府部门根据实际情况,会不定期地对连续路段的收费标准进行调整,根据政策涨价或降价。

    无聊的小A同学总喜欢研究一些稀奇古怪的问题,他开车在这条高速路上行驶时想到了这样一个问题:对于给定的l,r(l<r),在第l个到第r个收费站里等概率随机取出两个不同的收费站a和b,那么从a行驶到b将期望花费多少费用呢?

    输入输出格式

    输入格式:

    第一行2个正整数N,M,表示有N个收费站,M次调整或询问

    接下来M行,每行将出现以下两种形式中的一种

    C l r v 表示将第l个收费站到第r个收费站之间的所有道路的通行费全部增加v

    Q l r 表示对于给定的l,r,要求回答小A的问题

    所有C与Q操作中保证1<=l<r<=N

    输出格式:

    对于每次询问操作回答一行,输出一个既约分数

    若答案为整数a,输出a/1

    输入输出样例

    输入样例#1:
    4 5
    C 1 4 2
    C 1 2 -1
    Q 1 2
    Q 2 4
    Q 1 4
    
    输出样例#1:
    1/1
    8/3
    17/6
    

    说明

    所有C操作中的v的绝对值不超过10000

    在任何时刻任意道路的费用均为不超过10000的非负整数

    所有测试点的详细情况如下表所示



    数学期望+线段树+GCD(就约分用了)
    首先我们考虑在l到r之间的期望(第i到i+1为第i段,所以线段树长度为n-1)
    Σp val[p]*(r-i)*(i-l+1)/(r-l+1)*(r-l)
    我们来分析一下:
    分母部分为r-l+1个路段中选两个端点的方案种数
    分子部分考虑每一个位置p对期望的贡献可以得到
    接着要动态修改val值并查询答案
    把上式拆开:
    Σval[p]*(r-l*r)+val[p]*p*(l+r-1)-val[p]*p*p
    用一种支持区间修改查询的数据结构:线段树。来维护3种信息:区间signma(val[p]),signma(val[p]*p),signma(val[p]*p*p)
    signma(val[p])的维护:直接在和上+(r-l+1)*add
    signma(val[p]*p)的维护:利用等差数列公式,+(r-l+1)*(l+r)/2*add
    signma(val[p]*p*p)的维护:利用平方和公式:12+22+.....+n2=(2*n+1)*(n+1)*n/6
    注意long long小心整形溢出
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 using namespace std;
      6 typedef long long lol;
      7 struct Node
      8 {
      9     lol s[5];
     10     lol lazy;
     11     lol l,r;
     12 }c[400001];
     13 lol n,m;
     14 lol ans[5];
     15 //2signma(vp(L-LR)+vp*p(L+R-1)-vp*p*p)/(R-L+1)(R-L) 
     16 char get_op()
     17 {
     18     char ch=getchar();
     19     while (ch!='C'&&ch!='Q') ch=getchar();
     20     return ch;
     21 }
     22 lol gcd(lol x,lol y)
     23 {
     24     if (!y) return x;
     25     return gcd(y,x%y);
     26 } 
     27 lol get(lol r,lol l)
     28 {
     29     return ((2*r+1)*(r+1)*r/6-(2*l-1)*(l-1)*l/6);
     30 }
     31 void change(int rt,lol v)
     32 {
     33     c[rt].s[1]+=v*(c[rt].r-c[rt].l+1);
     34     c[rt].s[2]+=(c[rt].l+c[rt].r)*(c[rt].r-c[rt].l+1)/2*v;
     35     c[rt].s[3]+=v*(get(c[rt].r,c[rt].l));
     36     c[rt].lazy+=v;    
     37 }
     38 void pushup(int rt)
     39 {
     40     int i;
     41     for (i=1;i<=3;i++)
     42     {
     43         c[rt].s[i]=c[rt*2].s[i]+c[rt*2+1].s[i];
     44     }
     45 }
     46 void pushdown(int rt)
     47 {
     48     if (c[rt].lazy)
     49     {
     50         change(rt*2,c[rt].lazy);
     51         change(rt*2+1,c[rt].lazy);
     52         c[rt].lazy=0;
     53     }
     54 }
     55 void update(int rt,lol l,lol r,lol L,lol R,lol d)
     56 {
     57     if (l>=L&&r<=R)
     58     {
     59         change(rt,d);
     60         return;
     61     }
     62     lol mid=(l+r)/2;
     63     pushdown(rt);
     64     if (L<=mid) update(rt*2,l,mid,L,R,d);
     65     if (R>mid) update(rt*2+1,mid+1,r,L,R,d);
     66     pushup(rt);
     67 }
     68 lol query(int rt,lol l,lol r,lol L,lol R,int k)
     69 {
     70     if (l>=L&&r<=R)
     71     {
     72         return c[rt].s[k]; 
     73     }
     74     lol mid=(l+r)/2,ss=0;
     75     pushdown(rt);
     76     if (L<=mid) ss+=query(rt*2,l,mid,L,R,k);
     77     if (R>mid) ss+=query(rt*2+1,mid+1,r,L,R,k);
     78  pushup(rt);
     79  return ss;
     80 }
     81 void build(int rt,lol l,lol r)
     82 {
     83    c[rt].l=l;c[rt].r=r;
     84     if (l==r) return;
     85      lol mid=(l+r)/2;
     86      build(rt*2,l,mid);
     87       build(rt*2+1,mid+1,r);
     88 }
     89 int main()
     90 {lol i,l,r,j;
     91 lol p,d;
     92  char opt;
     93     cin>>n>>m;
     94     build(1,1,n-1);
     95      for (i=1;i<=m;i++)
     96      {
     97          opt=get_op();
     98          if (opt=='C') 
     99          {
    100              scanf("%lld%lld%lld",&l,&r,&d);
    101              update(1,1,n-1,l,r-1,d);
    102         }
    103         else 
    104         {
    105             scanf("%lld%lld",&l,&r);
    106             p=(r-l+1)*(r-l)/2;
    107             for (j=1;j<=3;j++)
    108              ans[j]=query(1,1,n-1,l,r-1,j);
    109              //cout<<ans[1]<<' '<<ans[2]<<' '<<ans[3]<<endl;
    110              ans[0]=(r-l*r)*ans[1]+(l+r-1)*ans[2]-ans[3];
    111              //cout<<ans[0]<<' '<<p<<endl;
    112              lol g=gcd(ans[0],p);
    113              printf("%lld/%lld
    ",ans[0]/g,p/g);
    114         }
    115      }
    116 }
     
  • 相关阅读:
    leetcode-242-Valid Anagram
    leetcode-232-Implement Queue using Stacks
    机器学习(3)——梯度下降法
    Codeforces Round #305 (Div. 2)D. Mike and Feet(单调栈)
    Codeforces Round #304 (Div. 2)(CF546D) Soldier and Number Game(线性筛)
    Codeforces Round #304 (Div. 2)(CF546E) Soldier and Traveling(最大流)
    机器学习(2)——线性回归法
    Codeforces Round #303 (Div. 2)(CF545) E Paths and Trees(最短路+贪心)
    机器学习(1)——K近邻算法
    简易解说拉格朗日对偶(Lagrange duality)(转载)
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7234968.html
Copyright © 2011-2022 走看看