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; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!