zoukankan      html  css  js  c++  java
  • #线段树#洛谷 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;
    }
    
  • 相关阅读:
    LeetCode 242. Valid Anagram (验证变位词)
    LeetCode 205. Isomorphic Strings (同构字符串)
    LeetCode 204. Count Primes (质数的个数)
    LeetCode 202. Happy Number (快乐数字)
    LeetCode 170. Two Sum III
    LeetCode 136. Single Number (落单的数)
    LeetCode 697. Degree of an Array (数组的度)
    LeetCode 695. Max Area of Island (岛的最大区域)
    Spark中的键值对操作
    各种排序算法总结
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14487730.html
Copyright © 2011-2022 走看看