zoukankan      html  css  js  c++  java
  • BZOJ 2752 [HAOI2012]高速公路(road)

    题解:线段树

    一开始维护错区间和,然后GG,不要凭感觉

    没把调试用的函数注释掉T了一发

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define lo now<<1
    #define ro now<<1|1
    using namespace std;
    const int maxn=100009;
    typedef long long Lint;
    
    
    int n,m;
    Lint si[maxn],si2[maxn];
    
    Lint Gcd(Lint a,Lint b){
    	if(b==0)return a;
    	return Gcd(b,a%b);
    }
    
    struct SegmentTree{
    	int l,r;
    	Lint tag;
    	Lint tl,sum,tr,dist;
    }tree[maxn<<2];
    
    
    void pushup(int now){
    	int ll=tree[lo].l;
    	int lr=tree[lo].r;
    	int rl=tree[ro].l;
    	int rr=tree[ro].r;
    	tree[now].sum=tree[lo].sum+tree[ro].sum+tree[lo].tr*(rr-rl+1)+tree[ro].tl*(lr-ll+1);
    	tree[now].dist=tree[lo].dist+tree[ro].dist;
    	tree[now].tl=tree[lo].tl+tree[ro].tl+tree[lo].dist*(rr-rl+1);
    	tree[now].tr=tree[lo].tr+tree[ro].tr+tree[ro].dist*(lr-ll+1);
    }
    
    
    void pushdown(int now){
    	int son;
    	Lint tag=tree[now].tag;
    	int l,r,len;
    	for(int i=0;i<=1;++i){
    		son=(now<<1|i);
    		tree[son].tag+=tag;
    		l=tree[son].l;r=tree[son].r;len=r-l+1;
    		tree[son].sum+=(tag*len*si[len]-tag*si2[len]+tag*si[len]);
    		tree[son].tl+=tag*si[len];
    		tree[son].tr+=tag*si[len];
    		tree[son].dist+=tag*(r-l+1);
    	}
    	tree[now].tag=0;
    }
    void check(int now){
    //	printf("%d %d %d %d
    ",tree[now].l,tree[now].r,tree[now].tl,tree[now].tr);
    	if(tree[now].l==tree[now].r)return;
    	pushdown(now);
    	check(lo);
    	check(ro);
    }
    void BuildTree(int now,int l,int r){
    	tree[now].l=l;tree[now].r=r;
    	tree[now].tag=tree[now].tl=tree[now].tr=tree[now].sum=tree[now].dist=0;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	BuildTree(lo,l,mid);
    	BuildTree(ro,mid+1,r);
    }
    
    void Updatasec(int now,int ll,int rr,Lint x){
    	if(tree[now].l>=ll&&tree[now].r<=rr){
    		tree[now].tag+=x;
    		int l=tree[now].l,r=tree[now].r;
    		int len=r-l+1;
    		tree[now].sum+=(x*len*si[len]-x*si2[len]+x*si[len]);
    		tree[now].tl+=si[len]*x;
    		tree[now].tr+=si[len]*x;
    		tree[now].dist+=(r-l+1)*x;
    		return;
    	}
    	pushdown(now);
    	int mid=(tree[now].l+tree[now].r)>>1;
    	if(ll<=mid)Updatasec(lo,ll,rr,x);
    	if(rr>mid)Updatasec(ro,ll,rr,x);
    	pushup(now);
    }
    
    Lint sum;
    void Querysum(int now,int ll,int rr,Lint &tl,Lint &tr,Lint &len){
    	if(tree[now].l>=ll&&tree[now].r<=rr){
    		sum+=tree[now].sum;
    		tl=tree[now].tl;
    		tr=tree[now].tr;
    		len=tree[now].dist;
    		return;
    	}
    	pushdown(now);
    	int mid=(tree[now].l+tree[now].r)>>1;
    	if(rr<=mid)Querysum(lo,ll,rr,tl,tr,len);
    	else if(ll>mid)Querysum(ro,ll,rr,tl,tr,len);
    	else{
    		Lint a,b,c,d,e,f;
    		Querysum(lo,ll,rr,a,b,c);
    		Querysum(ro,ll,rr,d,e,f);
    		int lb=max(tree[lo].l,ll);
    		int rb=min(tree[ro].r,rr);
    		tl=a+d+(c)*(rb-mid);
    		tr=b+e+(f)*(mid-lb+1);
    		len=c+f;
    		sum+=b*(rb-mid)+d*(mid-lb+1);
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		si[i]=si[i-1]+i;
    		si2[i]=si2[i-1]+1LL*i*i;
    	}
    	BuildTree(1,1,n-1);
    	
    	while(m--){
    		char opty=getchar();
    		int x,y,z;
    		Lint p1,p2,p3;
    		while(opty!='Q'&&opty!='C')opty=getchar();
    		scanf("%d%d",&x,&y);
    		--y;
    		if(opty=='Q'){
    			sum=0;
    			Querysum(1,x,y,p1,p2,p3);
    			Lint d=Gcd(sum,si[y-x+1]);
    			printf("%lld/%lld
    ",sum/d,si[y-x+1]/d);
    		}else{
    			scanf("%d",&z);
    			Updatasec(1,x,y,z*1LL);
    		}
    //		check(1);
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    GTest交流与经验总结
    linux i2c驱动架构-dm368 i2c驱动分析
    在不同编译环境中如何使用sleep()函数
    Android应用之基本的组件(一)
    Java Arrays Tutorial (3)
    ASP.NET中操作SQL数据库
    安卓开发06:布局-线性布局 LinearLayout
    在开发 ExtJS 应用程序常犯的 10 个错误
    每天4个linux命令--步骤一
    获取CPU序列号
  • 原文地址:https://www.cnblogs.com/zzyer/p/8503001.html
Copyright © 2011-2022 走看看