• #线段树#洛谷 2221 [HAOI2012]高速公路


    题目


    分析

    首先把收费站之间化为点,那这样即是区间加和区间查询,
    考虑求的应该是

    [frac{sum a[i]*(r-i+1)*(i-l+1)}{C(r-l+2,2)} ]

    分子可以拆成

    [a[i]*(l+r)*i-a[i]*(r+1)*(l-1)-a[i]*i*i ]

    关键是要维护(sum a[i],sum a[i]*i,sum a[i]*i*i)
    这个可以用(sum i=(i+1)*i/2,sum i^2=i*(i+1)*(2*i+1)/6)实现


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=100011; typedef long long lll;
    struct three{lll w0,w1,w2;}w[N<<2]; int lazy[N<<2],n;
    inline signed iut(){
    	rr int ans=0,f=1; rr char c=getchar();
    	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans*f;
    }
    inline void print(lll ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline three pup(three k1,three k2){return (three){k1.w0+k2.w0,k1.w1+k2.w1,k1.w2+k2.w2};}
    inline lll C(int n){return 1ll*n*(n-1)>>1;}
    inline lll calc(int n){return 1ll*n*(n+1)*(n<<1|1)/6;}
    inline void ptag(int k,int l,int r,int z){
    	w[k].w0+=(r-l+1)*z,w[k].w1+=(C(r+1)-C(l))*z,
    	w[k].w2+=(calc(r)-calc(l-1))*z,lazy[k]+=z;
    }
    inline void update(int k,int l,int r,int x,int y,int z){
    	if (l==x&&r==y){ptag(k,l,r,z); return;}
    	rr int mid=(l+r)>>1;
    	if (lazy[k]) ptag(k<<1,l,mid,lazy[k]),ptag(k<<1|1,mid+1,r,lazy[k]),lazy[k]=0;
    	if (y<=mid) update(k<<1,l,mid,x,y,z);
    	else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
    	    else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
    	w[k]=pup(w[k<<1],w[k<<1|1]);
    }
    inline three query(int k,int l,int r,int x,int y){
    	if (l==x&&r==y) return w[k];
    	rr int mid=(l+r)>>1;
    	if (lazy[k]) ptag(k<<1,l,mid,lazy[k]),ptag(k<<1|1,mid+1,r,lazy[k]),lazy[k]=0;
    	if (y<=mid) return query(k<<1,l,mid,x,y);
    	else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
    	    else return pup(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
    }
    signed main(){
    	n=iut()-1;
    	for (rr int m=iut();m;--m){
    		rr char c=getchar();
    		while (!isalpha(c)) c=getchar();
    		rr int l=iut(),r=iut()-1;
    		if (l>r) continue;
    		if (c=='C') update(1,1,n,l,r,iut());
    		else if (c=='Q'){
    			rr three Ans=query(1,1,n,l,r);
    			rr lll ans=Ans.w0*(r+1)*(1-l)+Ans.w1*(l+r)-Ans.w2;
    			rr lll ans2=C(r-l+2),GCD=__gcd(ans,ans2);
    			print(ans/GCD),putchar('/'),print(ans2/GCD),putchar(10);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    iOS:UIResponser控件的介绍(响应者)
    iOS:触摸控件UITouch、事件类UIEvent
    iOS:触摸事件和手势识别的介绍
    iOS:菜单控制器和菜单项:UIMenuController和UIMenuItem
    iOS:对GCD中 同步、异步、并行、串行的见解
    iOS:转载:同步、异步、并行、串行的详解
    iOS:GCD技术——仅仅执行一次和执行多次 dispatch_once和dispatch_apply
    pes and ts stream, how to convert
    5分钟搞定内存字节对齐
    sed 使用
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14487730.html
Copyright © 2020-2023  润新知