zoukankan      html  css  js  c++  java
  • HAOI2012高速公路bzoj2752 (线段树,数学)

    题目大意:
    给定一个长度为n的链,一共m次操作
    对于每次操作
    (C l r x)表示将第l个点到第r个点之间的所有道路的权值增加v

    (Q l r)在第l个到第r个点里等概率随机取出两个不同的点a和b,那么从a行驶到b将期望花费多少费用呢

    QwQ我们可以考虑将期望分为分子和分母两部分

    首先考虑分母,分母就是在(r-l+1)个点中选两个点的方案数,也就是({r-l+1}choose 2)

    而分子就是总权值了

    对于一个在([l,r])的点(i)来说
    它会被计算((i-l+1) imes (r-i+1))次 (就跟分别在左右两个区间枚举端点是一样的)

    那么我们求的东西也就变成了

    (sum_{i=l}^{r} w[i] imes(i-l+1) imes(r-i+1))

    我们考虑将它展开:
    (sum_{i=l}^{r} w[i] imes((r+l) imes i-i imes i +(r-l+1-r imes l)))

    再进一步来一波,对于区间([l,r])我们就是求的是:
    ((r+l) imes sum_{i=l}^{r}w[i] imes i + (r-l+1-r imes l) imes sum_{i=l}^{r}w[i] + sum_{i=l}^{r}w[i]*i^2)

    而对于更新,我们也不难找出一些规律了咯

    所以对于一个区间,我们只需要维护一个(w[i],w[i]*i,w[i]*i^2,i^2,i)的sigma值就能处理更新和合并了!

    void up(int root)
    {
    	f[root].si=f[2*root].si+f[2*root+1].si;
    	f[root].sii=f[2*root].sii+f[2*root+1].sii;
    	f[root].scostii=f[2*root].scostii+f[2*root+1].scostii;
    	f[root].scosti=f[2*root].scosti+f[2*root+1].scosti;
    	f[root].scost=f[2*root].scost+f[2*root+1].scost;
    }
    
    void pushdown(int root,int l,int r)
    {
       ll mid = (l+r) >> 1;
       if (add[root])
       {
       	  add[2*root]+=add[root];
       	  add[2*root+1]+=add[root];
       	  f[2*root].scost+=add[root]*(mid-l+1);
       	  f[2*root+1].scost+=add[root]*(r-mid);
       	  f[2*root].scosti+=add[root]*f[2*root].si;
       	  f[2*root+1].scosti+=add[root]*f[2*root+1].si;
       	  f[2*root].scostii+=add[root]*f[2*root].sii;
       	  f[2*root+1].scostii+=add[root]*f[2*root+1].sii;
       	  add[root]=0;
       }
    }
    

    emmmmm
    query的时候也记得( imes)的时候要乘询问的总区间,而不是当然区间!

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<map>
    #include<vector>
    #define ll long long
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 1e5+1e2;
    
    struct Node{
       ll scost,scosti,scostii,si,sii;
       ll ans;
    };
    
    Node f[4*maxn];
    ll add[4*maxn];
    int n,m;
    
    ll count(int xx,int yy)
    {
    	ll x=xx,y=yy;
    	return (y-x+1)*(y-x+2)/2;
    }
    
    void up(int root)
    {
    	f[root].si=f[2*root].si+f[2*root+1].si;
    	f[root].sii=f[2*root].sii+f[2*root+1].sii;
    	f[root].scostii=f[2*root].scostii+f[2*root+1].scostii;
    	f[root].scosti=f[2*root].scosti+f[2*root+1].scosti;
    	f[root].scost=f[2*root].scost+f[2*root+1].scost;
    }
    
    void pushdown(int root,int l,int r)
    {
       ll mid = (l+r) >> 1;
       if (add[root])
       {
       	  add[2*root]+=add[root];
       	  add[2*root+1]+=add[root];
       	  f[2*root].scost+=add[root]*(mid-l+1);
       	  f[2*root+1].scost+=add[root]*(r-mid);
       	  f[2*root].scosti+=add[root]*f[2*root].si;
       	  f[2*root+1].scosti+=add[root]*f[2*root+1].si;
       	  f[2*root].scostii+=add[root]*f[2*root].sii;
       	  f[2*root+1].scostii+=add[root]*f[2*root+1].sii;
       	  add[root]=0;
       }
    }
    
    void build(int root,int l,int r)
    {
    	if (l==r)
    	{
    		f[root].si=(long long)1LL*l;
    		f[root].sii=(long long) 1LL*l*l;
    		return;
    	}
    	int mid = (l+r) >> 1;
        build(2*root,l,mid);
        build(2*root+1,mid+1,r);
        up(root);
    }
    
    void update(int root,int l,int r,int x,int y,ll p)
    {
    	if (x<=l && r<=y)
    	{
    	    ll len=r-l+1;
    		f[root].scost+=1LL*p*len;
    		f[root].scosti+=1LL*p*f[root].si;
    		f[root].scostii+=1LL*p*f[root].sii;
    		add[root]+=p;
    		return;
    	}
    	pushdown(root,l,r);
    	int mid = (l+r) >> 1;
    	if (x<=mid) update(2*root,l,mid,x,y,p);
    	if (y>mid) update(2*root+1,mid+1,r,x,y,p);
    	up(root);
    }
    
    ll query(int root,int l,int r,int x,int y)
    {
    	if (x<=l && r<=y)
    	{
    		ll xx = x,yy=y;
    		return (long long)1LL*(xx+yy)*f[root].scosti+(long long)1LL*(yy-xx+1-xx*yy)*f[root].scost-f[root].scostii;
    	}
    	pushdown(root,l,r);
    	int mid = (l+r) >> 1;
    	ll ans=0;
    	if (x<=mid) ans+=query(2*root,l,mid,x,y);
    	if (y>mid) ans+=query(2*root+1,mid+1,r,x,y);
    	return ans;
    }
    
    int main()
    {
      scanf("%d%d",&n,&m);
      n--;
      build(1,1,n); 
      for (int i=1;i<=m;i++)
      {
      	 char s[10];
      	 scanf("%s",s+1);
      	 if (s[1]=='C')
      	 {
      	 	int x,y;
    	    ll z;
      	 	scanf("%d%d%lld",&x,&y,&z);
    		y--;
      	 	update(1,1,n,x,y,z);
    	   }
    	 if (s[1]=='Q')
    	 {
    	    int x,y;
    	    scanf("%d%d",&x,&y);
    	    y--;
    	    ll tmp=query(1,1,n,x,y);
    	    ll tmp1=count(x,y);
    	    printf("%lld/%lld
    ",tmp/__gcd(tmp1,tmp),tmp1/__gcd(tmp1,tmp));
    	 }
      }
      return 0;
    }
    
    
  • 相关阅读:
    java安装jdk时,执行javac出错
    servlet入门
    maven安装出错原因分析
    备份整个schema的数据
    备份db2schema数据
    UltraEdit使用技巧
    获取数据库分组后的最大值
    什么是jsp
    linux 上使用FTP传输文件
    关于opencv进行rtsp取流播放视频特别慢的问题记录
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160724.html
Copyright © 2011-2022 走看看