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\n",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\n",sum/d,si[y-x+1]/d);
		}else{
			scanf("%d",&z);
			Updatasec(1,x,y,z*1LL);
		}
//		check(1);
	}
	return 0;
}

  

posted @ 2018-03-03 20:58  ws_zzy  阅读(165)  评论(0编辑  收藏  举报