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

    II.[HAOI2012]高速公路

    本题已经在我的任务列表里挂了1年多了

    我们将这里的“期望”转成“\(\dfrac{\text{区间中任意两点间距离之和}}{\text{区间中选取两点的方案数}}\)。然后,我们考虑使用线段树维护区间中任意两点间距离之和。

    在每个节点上,我们维护如下东西:

    \(sum\):区间和

    \(len\):区间长度

    \(tag\):区间懒标记

    \(pre\):区间中每个点到区间中第一个点的距离之和

    \(suf\):区间中每个点到区间中最后一个点的距离之和

    \(all\):区间中任意两点间距离之和

    这个可以通过简单拼凑得到。

    时间复杂度\(O(n\log n)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll; 
    int n,m;
    ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
    #define lson x<<1
    #define rson x<<1|1
    #define mid ((l+r)>>1)
    #define C(x) (1ll*((x)+1)*(x)/2)
    struct SegTree{
    	int sum,len,tag;
    	ll all,pre,suf;
    	SegTree(){sum=len=tag=all=pre=suf=0;}
    	friend SegTree operator +(const SegTree &x,const SegTree &y){
    		SegTree z;
    		z.len=x.len+y.len;
    		z.sum=x.sum+y.sum;
    		z.pre=x.pre+y.pre+1ll*x.sum*y.len;
    		z.suf=y.suf+x.suf+1ll*y.sum*x.len;
    		z.all=x.all+y.all+x.suf*y.len+y.pre*x.len;
    		return z;
    	}
    	void ADD(int x){
    		sum+=x*len;
    		tag+=x;
    		pre+=C(len)*x;
    		suf+=C(len)*x;
    		all+=1ll*len*(len+1)*(len+2)/6*x;
    	}
    }seg[400100];
    #define pushdown(x) seg[lson].ADD(seg[x].tag),seg[rson].ADD(seg[x].tag),seg[x].tag=0
    void build(int x,int l,int r){
    	seg[x].len=r-l;
    	if(l+1==r)return;
    	build(lson,l,mid),build(rson,mid,r);
    }
    void modify(int x,int l,int r,int L,int R,int val){
    	if(l>=R||r<=L)return;
    	if(L<=l&&r<=R){seg[x].ADD(val);return;}
    	pushdown(x),modify(lson,l,mid,L,R,val),modify(rson,mid,r,L,R,val),seg[x]=seg[lson]+seg[rson];
    }
    SegTree query(int x,int l,int r,int L,int R){
    	if(l>=R||r<=L)return SegTree();
    	if(L<=l&&r<=R)return seg[x];
    	pushdown(x);
    	return query(lson,l,mid,L,R)+query(rson,mid,r,L,R);
    }
    void iterate(int x,int l,int r){
    	printf("[%d,%d):%d,%lld,%lld,%lld\n",l,r,seg[x].sum,seg[x].pre,seg[x].suf,seg[x].all);
    	if(l+1<r)pushdown(x),iterate(lson,l,mid),iterate(rson,mid,r),seg[x]=seg[lson]+seg[rson];
    	printf("[%d,%d):%d,%lld,%lld,%lld\n",l,r,seg[x].sum,seg[x].pre,seg[x].suf,seg[x].all);
    }
    char c[10];
    int main(){
    	scanf("%d%d",&n,&m),build(1,1,n);
    	for(int i=1,l,r,v;i<=m;i++){
    		scanf("%s%d%d",c,&l,&r);
    		if(c[0]=='C')scanf("%d",&v),modify(1,1,n,l,r,v);
    		else{
    			ll x=query(1,1,n,l,r).all,y=C(r-l);
    			ll GCD=gcd(y,x);
    			printf("%lld/%lld\n",x/GCD,y/GCD);
    		}
    //		iterate(1,1,n);
    	}
    	return 0;
    } 
    

  • 相关阅读:
    multimap-begin
    multimap-constructors
    multimap-constructors
    map-rend
    map-rend
    map-rbegin
    map-rbegin
    lower_bound
    纪念邓小平同志诞辰110周年,2014年出品的48集电视剧《历史转折中的邓小平》
    二叉查找树(二叉排序树)的详细实现,以及随机平衡二叉查找树Treap的分析与应用
  • 原文地址:https://www.cnblogs.com/Troverld/p/14610838.html
Copyright © 2011-2022 走看看