• BZOJ 2752: [HAOI2012]高速公路(road)(线段树)


    解题思路

      对于一段区间考虑每条边的贡献,即(ans=sumlimits_{i=l}^{r-1}(i-l+1)*(r-i)*w(i)),把这个暴力展开,得到一个关于(i)的多项式,然后发现只需要维护(sum a(i))(sum a(i)*i)(sum a(i)*i^2),线段树维护即可。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #define int long long
    
    using namespace std;
    const int N=100005;
    typedef long long LL;
    
    inline int rd(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    
    int n,m;
    LL sum0[N<<2],sum1[N<<2],sum2[N<<2];
    LL tag0[N<<2],tag1[N<<2],tag2[N<<2];
    LL a1[N],a2[N];
    
    inline void pushdown(int x,int l,int r){
    	int mid=(l+r)>>1;
    	if(tag0[x]){
    		sum0[x<<1]+=tag0[x]*(mid-l+1);
    		sum0[x<<1|1]+=tag0[x]*(r-mid);
    		tag0[x<<1]+=tag0[x]; tag0[x<<1|1]+=tag0[x];
    		tag0[x]=0;
    	}
    	if(tag1[x]){
    		sum1[x<<1]+=tag1[x]*(a1[mid]-a1[l-1]);
    		sum1[x<<1|1]+=tag1[x]*(a1[r]-a1[mid]);
    		tag1[x<<1]+=tag1[x]; tag1[x<<1|1]+=tag1[x];
    		tag1[x]=0;
    	}
    	if(tag2[x]){
    		sum2[x<<1]+=tag2[x]*(a2[mid]-a2[l-1]);
    		sum2[x<<1|1]+=tag2[x]*(a2[r]-a2[mid]);
    		tag2[x<<1]+=tag2[x]; tag2[x<<1|1]+=tag2[x];
    		tag2[x]=0;
    	}
    }
    
    void update(int x,int l,int r,int L,int R,int k){
    	if(L<=l && r<=R) {
    		sum0[x]+=(r-l+1)*k; tag0[x]+=k;
    		sum1[x]+=(LL)(a1[r]-a1[l-1])*k; tag1[x]+=k;
    		sum2[x]+=(LL)(a2[r]-a2[l-1])*k; tag2[x]+=k;
    		return ;
    	}
    	int mid=(l+r)>>1;pushdown(x,l,r);
    	if(L<=mid) update(x<<1,l,mid,L,R,k);
    	if(mid<R) update(x<<1|1,mid+1,r,L,R,k);
    	sum0[x]=sum0[x<<1]+sum0[x<<1|1];
    	sum1[x]=sum1[x<<1]+sum1[x<<1|1];
    	sum2[x]=sum2[x<<1]+sum2[x<<1|1];
    }
    
    LL query0(int x,int l,int r,int L,int R){
    	if(L<=l && r<=R) return sum0[x];
    	int mid=(l+r)>>1; LL ret=0; pushdown(x,l,r);
    	if(L<=mid) ret+=query0(x<<1,l,mid,L,R);
    	if(mid<R) ret+=query0(x<<1|1,mid+1,r,L,R);
    	return ret;
    }
    
    LL query1(int x,int l,int r,int L,int R){
    	if(L<=l && r<=R) return sum1[x];
    	int mid=(l+r)>>1; LL ret=0; pushdown(x,l,r);
    	if(L<=mid) ret+=query1(x<<1,l,mid,L,R);
    	if(mid<R) ret+=query1(x<<1|1,mid+1,r,L,R);
    	return ret;
    }
    
    LL query2(int x,int l,int r,int L,int R){
    	if(L<=l && r<=R) return sum2[x];
    	int mid=(l+r)>>1; LL ret=0; pushdown(x,l,r);
    	if(L<=mid) ret+=query2(x<<1,l,mid,L,R);
    	if(mid<R) ret+=query2(x<<1|1,mid+1,r,L,R);
    	return ret;
    }
    
    LL gcd(LL x,LL y){
    	if(!y) return x;
    	return gcd(y,x%y);
    }
    
    signed main(){
    	n=rd(),m=rd(); 
    	for(int i=1;i<n;i++) a1[i]=a1[i-1]+i;
    	for(int i=1;i<n;i++) a2[i]=a2[i-1]+(LL)i*i;
    	char c; int l,r,k; LL ans,now,GCD;
    	while(m--){
    		c=getchar(); while(c!='C' && c!='Q') c=getchar();
    		if(c=='C'){
    			l=rd(),r=rd()-1,k=rd();
    			update(1,1,n,l,r,k);
    		}
    		else {
    			l=rd(),r=rd()-1; now=(r-l+2)*(r-l+1)/2;
    			ans=-query2(1,1,n,l,r)+query1(1,1,n,l,r)*(l+r)-query0(1,1,n,l,r)*(l*r+l-r-1);
    			GCD=gcd(ans,now); ans/=GCD; now/=GCD;
    			printf("%lld/%lld
    ",ans,now);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    TCP链接异常断开后,对端仍然ESTABLISH
    mds0: Many clients (191) failing to respond to cache pressure
    Linux C/C++编译过程中的各种not declared in this scope
    Centos7添加磁盘并分区格式化
    Windows Terminal——安装并配置主题
    Kbone——创建项目报错 name can no longer contain capital letters
    Redis——大批量删除redis的key
    Redis——设置最大内存 | key淘汰机制
    Nightingale——滴滴夜莺部署【一】
    ELK——使用Docker快速搭建
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10286071.html
Copyright © 2020-2023  润新知