• Bzoj2752: [HAOI2012]高速公路(road)


    Bzoj2752: [HAOI2012]高速公路(road)

    比较恶心的一道题,关键在于r的加1减1搞得很乱。所以以下的r都是原题给出的r,并没有减1。

    其实这道题是一个假的期望,答案就是区间的所有子区间和除以$C_{len}^2$,然后就考虑如何求所有子区间和,

    直接暴力枚举肯定不行,可以像‘树上染色’一样考虑每个点的贡献,对于点i,他的贡献为$s[i]*(i-l+1)*(r-i)$其实就是选到i点左边(包括自己)的方案数以及选到右边的方案数,乘起来就是i点作出贡献的次数,再乘上s[i].那么我们最终要求的就是$∑s[i]*(i-l+1)*(r-i)$,这样看式子当然看不出来什么,试着把它拆开,得到

    $∑(l+r-1)*s[i]*i-s[i]*i^2+(r-l*r)*s[i]$,即$(l+r-1)*∑s[i]*i-∑s[i]*i^2+(r-l*r)*∑s[i]$,这样就可以用线段树维护s[i],s[i]*i,s[i]*i*i,通过普通的线段树就可以做出来了。

      1 #include<iostream>
      2 #include<cstdio>
      3 #define int long long
      4 using namespace std;
      5 struct tree
      6 {
      7     int l,r,sum1,sum2,sum3,sumi,sumi2,la;
      8     #define l(x) tr[x].l
      9     #define r(x) tr[x].r
     10     #define sum1(x)  tr[x].sum1
     11     #define sum2(x)  tr[x].sum2
     12     #define sum3(x)  tr[x].sum3
     13     #define sumi(x)  tr[x].sumi
     14     #define sumi2(x) tr[x].sumi2
     15     #define la(x)    tr[x].la
     16 }tr[400010];
     17 int gcd(int a,int b){return !b?a:gcd(b,a%b);}
     18 int n,m;
     19 
     20 void pushup(int x)
     21 {
     22     int ls=x*2,rs=x*2+1;
     23     sum1(x)=sum1(ls)+sum1(rs);
     24     sum2(x)=sum2(ls)+sum2(rs);    
     25     sum3(x)=sum3(ls)+sum3(rs);
     26     sumi(x)=sumi(ls)+sumi(rs);
     27     sumi2(x)=sumi2(ls)+sumi2(rs);
     28 }
     29 void build(int l,int r,int x)
     30 {
     31     l(x)=l,r(x)=r;
     32     if(l==r)
     33     {
     34         sumi(x)=l,
     35         sumi2(x)=l*l;
     36         return;
     37     }
     38     int mid=(l+r)>>1;
     39     build(l,mid,x*2);
     40     build(mid+1,r,x*2+1);
     41     pushup(x);
     42 }
     43 void down(int x)
     44 {
     45     if(l(x)==r(x))return;
     46     if(!la(x))return;
     47     int ls=x*2,rs=x*2+1;
     48     la(ls)+=la(x),la(rs)+=la(x);    
     49     sum1(ls)+=(r(ls)-l(ls)+1)*la(x);
     50     sum1(rs)+=(r(rs)-l(rs)+1)*la(x);    
     51     sum2(ls)+=sumi(ls)*la(x);
     52     sum2(rs)+=sumi(rs)*la(x);
     53     sum3(ls)+=sumi2(ls)*la(x);
     54     sum3(rs)+=sumi2(rs)*la(x);
     55     la(x)=0;
     56     pushup(x);
     57 }
     58 void add(int l,int r,int x,int y)
     59 {    
     60     if(l(x)==r(x))
     61     {
     62         sum1(x)+=y;
     63         sum2(x)+=l(x)*y;
     64         sum3(x)+=l(x)*l(x)*y;
     65         return;
     66     }
     67     down(x);
     68     if(l(x)>=l&&r(x)<=r)
     69     {
     70         la(x)+=y;
     71         down(x);
     72         return;
     73     }
     74     int mid=(l(x)+r(x))>>1;
     75     if(l<=mid)add(l,r,x*2,y);
     76     if(r>mid) add(l,r,x*2+1,y);
     77     pushup(x);
     78 }
     79 int ask1(int l,int r,int x)
     80 {
     81     down(x);
     82     if(l(x)>=l&&r(x)<=r)
     83         return sum1(x);
     84     int ans=0,mid=(l(x)+r(x))>>1;
     85     if(l<=mid)ans+=ask1(l,r,x*2);
     86     if(r>mid) ans+=ask1(l,r,x*2+1);
     87     return ans;
     88 }
     89 int ask2(int l,int r,int x)
     90 {
     91     down(x);
     92     if(l(x)>=l&&r(x)<=r)return sum2(x);    
     93     int ans=0,mid=(l(x)+r(x))>>1;
     94     if(l<=mid)ans+=ask2(l,r,x*2);
     95     if(r>mid) ans+=ask2(l,r,x*2+1);
     96     return ans;
     97 }
     98 int ask3(int l,int r,int x)
     99 {
    100     down(x);    
    101     if(l(x)>=l&&r(x)<=r)return sum3(x);
    102     int ans=0,mid=(l(x)+r(x))>>1;
    103     if(l<=mid)ans+=ask3(l,r,x*2);
    104     if(r>mid) ans+=ask3(l,r,x*2+1);
    105     return ans;
    106 }
    107 signed main()
    108 {
    109     cin>>n>>m;n--;
    110     build(1,n,1);
    111     char op[3];int l,r,v;
    112     for(int i=1;i<=m;i++)    
    113     {
    114         cin>>op>>l>>r;
    115         if(op[0]=='C')
    116         {
    117             cin>>v;
    118             add(l,r-1,1,v);
    119         }    
    120         else
    121         {
    122             int ans=(l+r-1)*ask2(l,r-1,1)-ask3(l,r-1,1)+(r-l*r)*ask1(l,r-1,1);
    123 //            cout<<ask2(l,r-1,1)<<" "<<ask3(l,r-1,1) <<" "<<ask1(l,r-1,1)<<endl;
    124             int len=r-l+1,tem;    
    125             tem=len*(len-1)/2;
    126             int GCD=gcd(ans,tem);
    127             if(ans==0)puts("0/1");
    128             else printf("%lld/%lld
    ",ans/GCD,tem/GCD);
    129         }
    130     }
    131 }
    View Code
  • 相关阅读:
    非post请求时整个url作为参数传递出现bug
    UML类图及类与类之间的关系
    MyBatis中if,where,set标签
    MySQL主从复制配置遇到的部分问题
    SpringMVC的各种参数绑定方式
    对解释器模式的认识
    大型网站技术架构案例分析
    淘宝网质量属性描述
    阅读架构漫谈笔记
    阅读计划——《软件需求十步走》06
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11240208.html
Copyright © 2020-2023  润新知