SDOI2017相关分析

SDOI2017相关分析

一道线段树水题

注意别被卡精度(无时无刻都要想着强制转换double)

居然写了\(100min\),我太弱了!!!

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f==1?x:-x;
}
const int N=1e5+4;
#define lc (p<<1)
#define rc (p<<1|1)
int n,m,a[N],b[N];
double t[N<<2],tx[N<<2],dx[N<<2],dy[N<<2],lzmx[N<<2],lzmy[N<<2],lzcx[N<<2],lzcy[N<<2];
double ans,anx,ax,ay;
inline void pushup(int p){
    t[p]=t[lc]+t[rc];
    tx[p]=tx[lc]+tx[rc];
    dx[p]=dx[lc]+dx[rc];
    dy[p]=dy[lc]+dy[rc];
}
inline void pushmo(int p,int l,int r,double x,double y){
    t[p]+=dx[p]*y+dy[p]*x+x*y*(r-l+1);
    tx[p]+=x*2*dx[p]+x*x*(r-l+1);
    dx[p]+=x*(r-l+1);
    dy[p]+=y*(r-l+1);
    lzmx[p]+=x;
    lzmy[p]+=y;
}
inline double ii(double x){
    return x*(x+1)*(x*2+1)/6;
}
inline void pushco(int p,int l,int r,double x,double y){
    lzmx[p]=lzmy[p]=0;
    t[p]=ii(r)-ii(l-1)+(x+y)*(l+r)*(r-l+1)/2+x*y*(r-l+1);
    tx[p]=ii(r)-ii(l-1)+x*2*(l+r)*(r-l+1)/2+x*x*(r-l+1);
    dx[p]=x*(r-l+1)+(double)(l+r)*(r-l+1)/2;//double
    dy[p]=y*(r-l+1)+(double)(l+r)*(r-l+1)/2;
    lzcx[p]=x;lzcy[p]=y;
}
inline void pushdown(int p,int l,int mid,int r){
    if(lzcx[p]||lzcy[p]){
        pushco(lc,l,mid,lzcx[p],lzcy[p]);
        pushco(rc,mid+1,r,lzcx[p],lzcy[p]);
        lzcx[p]=lzcy[p]=0;
    }
    if(lzmx[p]||lzmy[p]){
        pushmo(lc,l,mid,lzmx[p],lzmy[p]);
        pushmo(rc,mid+1,r,lzmx[p],lzmy[p]);
        lzmx[p]=lzmy[p]=0;
    }
}
inline void build(int p,int l,int r){
    if(l==r){
        t[p]=(double)a[l]*b[l];
        tx[p]=(double)a[l]*a[l];
        dx[p]=a[l];
        dy[p]=b[l];
        return;
    }
    int mid=(l+r)>>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
    pushup(p);
}
inline void modify(int p,int l,int r,int ql,int qr,double x,double y){
    if(ql<=l&&r<=qr){
        pushmo(p,l,r,x,y);
        return;
    }
    int mid=l+r>>1;
    pushdown(p,l,mid,r);
    if(ql<=mid)modify(lc,l,mid,ql,qr,x,y);
    if(mid<qr)modify(rc,mid+1,r,ql,qr,x,y);
    pushup(p);
}
inline void cover(int p,int l,int r,int ql,int qr,double x,double y){
    if(ql<=l&&r<=qr){
        pushco(p,l,r,x,y);
        return;
    }
    int mid=l+r>>1;
    pushdown(p,l,mid,r);
    if(ql<=mid)cover(lc,l,mid,ql,qr,x,y);
    if(mid<qr)cover(rc,mid+1,r,ql,qr,x,y);
    pushup(p);
}
inline void query(int p,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){
        ans+=t[p];
        anx+=tx[p];
        ax+=dx[p];
        ay+=dy[p]; 
        return;
    }
    int mid=l+r>>1;
    pushdown(p,l,mid,r);
    if(ql<=mid)query(lc,l,mid,ql,qr);
    if(mid<qr)query(rc,mid+1,r,ql,qr);
}
int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++)b[i]=read();
    build(1,1,n);
    while(m--){
        static int op,l,r,x,y;
        op=read();l=read();r=read();
        if(op==1){
            ans=anx=ax=ay=0;
            query(1,1,n,l,r);
            l=r-l+1;
            printf("%.8lf\n",(ans-ax*ay/l)/(anx-ax*ax/l));
            continue;
        }
        x=read();y=read();
        if(op==2)modify(1,1,n,l,r,x,y);
        else cover(1,1,n,l,r,x,y);
    }
    return (0-0);
}
上一篇:线段树区间操作集合


下一篇:"Ray, Pass me the dishes!" UVA - 1400(线段树区间合并)