haoi2012高速公路

链接:https://www.luogu.org/problemnew/show/P2221

根本不会做,只能模yzy大佬。方法类似于维修数列的统计最大字段和,用线段树维护当前区间答案,然后通过一系列计算从左右区间合并得到当前区间答案。这题维护的东西有些复杂,一个前缀和的和、后缀和的和,更新也要用一个玄学数列的通项公式(不过也可以预处理)。。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=100010;
struct gg{
    ll ls,rs,l,r,add,qz,hz,sum,w;
    gg(){ls=0,rs=0,l=1e16,r=-1e16,add=0,qz=0,hz=0,sum=0,w=0;}
}node[N*5];
int n,m;
ll sigma(ll x)
{return (1LL+x)*x/2LL;}
ll gcd(ll x,ll y)
{return !y?x:gcd(y,x%y);}
void push_up(int x)
{
    int ls,rs;
    ls=node[x].ls,rs=node[x].rs;//cout<<x<<" "<<node[ls].l<<" "<<node[ls].r<<" "<<node[rs].l<<" "<<node[rs].r<<endl;
    node[x].w=node[ls].w+node[rs].w+node[ls].hz*max(0LL,node[rs].r-node[rs].l+1)+node[rs].qz*max(0LL,node[ls].r-node[ls].l+1);
    node[x].sum=node[ls].sum+node[rs].sum;
    node[x].hz=max(0LL,(node[ls].r-node[ls].l+1))*node[rs].sum+node[ls].hz+node[rs].hz;
    node[x].qz=max(0LL,(node[rs].r-node[rs].l+1))*node[ls].sum+node[rs].qz+node[ls].qz;
}
void upd(int x,ll v)
{
    ll tmp=node[x].r-node[x].l+1;
    node[x].sum+=tmp*v;
    node[x].qz+=sigma(tmp)*v;
    node[x].hz+=sigma(tmp)*v;
    node[x].w+=tmp*(tmp+1)*(tmp+2)/6*v;
    node[x].add+=v;
}
void push_down(int x)
{
    if(node[x].add)
    {
        if(node[x].ls)upd(node[x].ls,node[x].add);
        if(node[x].rs)upd(node[x].rs,node[x].add);
        node[x].add=0;
    }
}
gg merge(gg x,gg y)
{
    gg res=gg();
    res.w=x.w+y.w+x.hz*max(0LL,(y.r-y.l+1))+y.qz*max(0LL,(x.r-x.l+1));
    res.sum=x.sum+y.sum;
    res.hz=max(0LL,(x.r-x.l+1))*y.sum+x.hz+y.hz;
    res.qz=max(0LL,(y.r-y.l+1))*x.sum+y.qz+x.qz;
    res.l=min(x.l,y.l),res.r=max(x.r,y.r);
    return res;
}
int build(int l,int r,int k)
{
    int mid;
    node[k]=gg(),node[k].l=l,node[k].r=r;
    if(l!=r)
    {
        mid=(l+r)>>1;
        if(l<=mid)node[k].ls=build(l,mid,k<<1);
        if(r>mid)node[k].rs=build(mid+1,r,k<<1|1);
    }
    return k;
}
void cg(int x,int l,int r,ll v)
{
    if(node[x].r<l||node[x].l>r)return;
    push_down(x);
    if(l<=node[x].l&&node[x].r<=r)
    {
        upd(x,v);
        return;
    }
    if(node[x].ls)cg(node[x].ls,l,r,v);
    if(node[x].rs)cg(node[x].rs,l,r,v);
    push_up(x);
}
gg ask(int x,int l,int r)
{
    if(node[x].r<l||node[x].l>r)return gg();
    push_down(x);
    if(l<=node[x].l&&node[x].r<=r)return node[x];
    gg L=gg(),R=gg();
    if(node[x].ls)L=ask(node[x].ls,l,r);
    if(node[x].rs)R=ask(node[x].rs,l,r);
    return merge(L,R);
}
void print(ll x,ll y)
{
    ll G;
    G=gcd(x,y),x/=G,y/=G;
    printf("%lld/%lld\n",x,y);
}
int main()
{
    node[0]=gg();
    char op;int l,r;ll v;gg res;
    scanf("%d%d",&n,&m);
    build(1,n-1,1);
    for(int i=1;i<=m;i++)
    {
        scanf(" %c",&op);
        if(op=='C')
        {
            scanf("%d%d%lld",&l,&r,&v),--r;
            cg(1,l,r,v);
        }
        else
        {
            scanf("%d%d",&l,&r),--r;
            res=ask(1,l,r);
            print(res.w,1LL*(r-l+2)*(r-l+1)/2LL);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/caoyang1123/article/details/81587177