問題--HAOI2012高速道路へのマジカル頭脳ホール・ソリューション(数学的期待、ツリーライン)

 

ポータル:COGS

実際に、私はこの質問には力の無知で取得します。最初の感覚は、パスセグメントツリーのメンテナンスコスト、およびその後なくなっていることです。

実際には、それはまだ謎のいくつかに記載されていなければならない、それについて考えます。

ツリーラインと体重維持の道はそれが右の幼稚園をオンにしません、個人の意志です。

しかし、どのように予想を下回っ数えますか?

Rが実際に期待されている - 期待はその後、間隔Lのために、加重平均である、コーチが話しだと思います

これは、分子であります

NATURAL分母は(RL + 1)*(RL)/ 2であります

しかし、このいまいましい事がああ見つけるために、通常のセグメントツリーを使用することはできませんようです。

オープン彼を与えることができない方法を見つけるには?

区間[L、R]期待のために考えてみて、実際には、道路の部分は完全に数回を忘れていますか?

Rの天然セグメント道路用のL、(RL + 1)倍、L + 1はパラ(RL)+(RL)である//さ回L + 1から始まる数

道路それのL + 2セグメント?(RL-1)* 3 //数3がRにL + 2から開始することで、この時間は何かを見つけることができませんか?

あります。

しかし、セグメントツリーああ、まだできていないようでそれが解体し続けます

1つの式にしこりの背中を考えてみましょう、我々が得ることができます

 

それは見つけることができるものではありませんか?

式全体が1であり、三つの部分に分割することができ、私用のエントリが存在し、それらが間隔を変更するために関与され、クエリ内のLとRが一定とみなすことができるので、私は、次に、Iを*ため、エントリが存在しますこれは、式は、それぞれ、三つの部分を維持することができるのですか?

想定メンテナンスSUM1、SUM2、SUM3、SUM1間隔の[i]の和のすべてを維持し、SUM2 [i]は* i個の和のすべてを維持し、SUM3全ての[i]は* iは、その合計を維持します*

変更方法については、今節?

(x + y)は、よく知られている乗算にわたって分配Z = XZ + YZ、 及びため道路のために、私は私達が私はすべてのために、それぞれ二つの補助変数、sum4、sum5を追加することができる場合、その後、固定し、間隔すべての私は* と?

正確:今W +つまり、すべての要素の間隔内で、次いでSUM1 = SUM1 +インターバル長* W、SUM2 = SUM2 + sum4 * W =すべて([I] + W)*全てのi =すべて[Iとし] *すべての私は、私は同じ理由SUM3のために、すべての* W +。

那么,我们就可以愉快的维护一个含有5个元素的线段树了,最终的期望答案就是sum1*(R-L-LR+1)+sum2*(L+R)-sum3,然后除去前面算好的分母即可。

注意,此题细节问题很多,代码中的注释几乎都是调试时输出的辅助量,用来判断程序某一部分的正确性的。

补一句,这一题给出的区间是收费站,也就是端点,但是为了应用线段树,手动将左边界++即可(相当于每个区间的序号是自己右边的收费站)

代码:

 

#include<iostream>
#include<cstdio>
#include<vector>
#define int long long int
using namespace std;
struct PE
{
    int lazy,sum1,sum2,sum3,sum4,sum5,l,r;
    //sum1=∑a[i]
    //sum2=∑a[i]*i
    //sum3=∑a[i]*i*i
    //sum4=∑i;
    //sum5=∑i*i;
    //4,5用于更新2,3 
};
PE t[400001];
int a[100001];
int n,m,a1,a2,a3;
char xd;
int ls(int x)
{
    return x<<1;
}
int rs(int x)
{
    return x<<1|1;
}
void pushup(int x)
{
    t[x].sum1=t[ls(x)].sum1+t[rs(x)].sum1;
    t[x].sum2=t[ls(x)].sum2+t[rs(x)].sum2;
    t[x].sum3=t[ls(x)].sum3+t[rs(x)].sum3;
    
    t[x].l=t[ls(x)].l;
    t[x].r=t[rs(x)].r;
}
void build(int x,int l,int r)
{
    if(l==r)
    {
        t[x].sum1=a[l];
        t[x].sum2=a[l]*l;
        t[x].sum3=a[l]*l*l;
        t[x].sum4=l;
        t[x].sum5=l*l;
        t[x].lazy=0;
        t[x].l=t[x].r=l;
        return ; 
    }
    int mid=(l+r)>>1;
    build(ls(x),l,mid);
    build(rs(x),mid+1,r);
    t[x].sum4=t[ls(x)].sum4+t[rs(x)].sum4;
    t[x].sum5=t[ls(x)].sum5+t[rs(x)].sum5;
    pushup(x);
}
void pushdown(int x,int l,int r)
{
    int mid=(l+r)>>1;
    if(t[x].lazy)
    {
        t[ls(x)].lazy+=t[x].lazy;
        t[rs(x)].lazy+=t[x].lazy;
        t[ls(x)].sum1+=(mid-l+1)*t[x].lazy;
        t[rs(x)].sum1+=(r-mid)*t[x].lazy;
        t[ls(x)].sum2+=(t[ls(x)].sum4*t[x].lazy);
        t[ls(x)].sum3+=(t[ls(x)].sum5*t[x].lazy);
        t[rs(x)].sum2+=(t[rs(x)].sum4*t[x].lazy);
        t[rs(x)].sum3+=(t[rs(x)].sum5*t[x].lazy);
        t[x].lazy=0;
    }
}
void QZADD(int x,int l,int r,int nl,int nr,int w)
{
    if(nl<=l&&nr>=r)
    {
        t[x].sum1+=(r-l+1)*w;
        t[x].sum2+=(t[x].sum4*w);
        t[x].sum3+=(t[x].sum5*w);
        t[x].lazy+=w;
        return;
    }
    pushdown(x,l,r);
    int mid=(l+r)>>1;
    if(nl<=mid)
        QZADD(ls(x),l,mid,nl,nr,w);
    if(nr>mid)
        QZADD(rs(x),mid+1,r,nl,nr,w);
    pushup(x);
}
int QZQUERY1(int x,int l,int r,int nl,int nr)
{
    int kel=0;
    if(nl<=l&&nr>=r)
    {
        return t[x].sum1;
    }
    pushdown(x,l,r);
    int mid=(l+r)>>1;
    if(nl<=mid)
        kel+=QZQUERY1(ls(x),l,mid,nl,nr);
    if(nr>mid)
        kel+=QZQUERY1(rs(x),mid+1,r,nl,nr);
    return kel;
}
int QZQUERY2(int x,int l,int r,int nl,int nr)
{
    int kel=0;
    if(nl<=l&&nr>=r)
    {
        return t[x].sum2;
    }
    pushdown(x,l,r);
    int mid=(l+r)>>1;
    if(nl<=mid)
        kel+=QZQUERY2(ls(x),l,mid,nl,nr);
    if(nr>mid)
        kel+=QZQUERY2(rs(x),mid+1,r,nl,nr);
    return kel;
}
int QZQUERY3(int x,int l,int r,int nl,int nr)
{
    int kel=0;
    if(nl<=l&&nr>=r)
    {
        return t[x].sum3;
    }
    pushdown(x,l,r);
    int mid=(l+r)>>1;
    if(nl<=mid)
        kel+=QZQUERY3(ls(x),l,mid,nl,nr);
    if(nr>mid)
        kel+=QZQUERY3(rs(x),mid+1,r,nl,nr);
    return kel;
}
int QUERY(int l,int r)
{
    int s=0;
    s+=QZQUERY1(1,1,n,l,r)*(r-l-r*l+1);
    //cout<<QZQUERY1(1,1,n,l,r)<<' ';
    s+=QZQUERY2(1,1,n,l,r)*(l+r);
    //cout<<QZQUERY2(1,1,n,l,r)<<' ';
    s-=QZQUERY3(1,1,n,l,r);
    //cout<<QZQUERY3(1,1,n,l,r)<<'*'<<endl;
    return s;
}
int GCD(int x,int y)
{
    return y==0?x:GCD(y,x%y);
}
int LINYIN()
{
    freopen("roadxw.in","r",stdin);
    freopen("roadxw.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        cin>>xd;
        if(xd=='C')
        {
            scanf("%lld%lld%lld",&a1,&a2,&a3);
            QZADD(1,1,n,a1+1,a2,a3);
        }
        else
        {
            scanf("%d%d",&a1,&a2);
            int kel=QUERY(a1+1,a2);
            int s=(a2-a1+1)*(a2-a1)/2;
            int G=GCD(s,kel);
            //cout<<endl<<kel<<' '<<s<<' '<<G<<endl; 
            printf("%lld/%lld\n",kel/G,s/G);
        }
    }
    return 0;
}
int LWH=LINYIN();
signed main()
{
    ;
}

 

完结撒花!

 

おすすめ

転載: www.cnblogs.com/XLINYIN/p/11780232.html