ポータル: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() { ; }
完结撒花!