• BZOJ 4821: [Sdoi2017]相关分析 线段树 + 卡精


    考试的时候切掉了,然而卡精 + 有一个地方忘开 $long long$,完美挂掉 $50$pts. 

    把式子化简一下,然后直接拿线段树来维护即可. 

    Code: 

    // luogu-judger-enable-o2
    // luogu-judger-enable-o2
    #include <cstdio> 
    #include <algorithm>    
    #define N 130304      
    #define ll double 
    #define ldb long double 
    #define setIO(s) freopen(s".in","r",stdin)  , freopen(s".out","w",stdout)      
    using namespace std;    
    namespace IO 
    {
        char *p1, *p2, buf[100000];
    
        #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
    
        int rd() {
        	int x = 0, f = 1;
    	    char c = nc();
        	while (c < 48) {
                if (c == '-')
                    f = -1;
                c = nc();
            }
            while (c > 47) {
                x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
            }
            return x * f;
        }
    };    
    int n,Q; 
    ll X[N], Y[N];     
    ll sqr[N],sum[N];        
    struct Node 
    {
        ll x,y,xy,add_t, add_s, set_s, set_t,sqr;     
        int set_tag;                 
    }t[N<<2];   
    inline void pushup(int l,int r,int now) 
    {
        int mid=(l+r)>>1;  
        if(mid>=l) 
        {
            t[now].x=t[now<<1].x; 
            t[now].y=t[now<<1].y; 
            t[now].xy=t[now<<1].xy;  
            t[now].sqr=t[now<<1].sqr;    
        }
        if(r>mid)  
        {
            t[now].x+=t[now<<1|1].x; 
            t[now].y+=t[now<<1|1].y; 
            t[now].xy+=t[now<<1|1].xy;  
            t[now].sqr+=t[now<<1|1].sqr;          
        }
    }   
    inline void mark1(int l,int r,int now,ll S,ll T) 
    {
        t[now].add_s+=S, t[now].add_t+=T;         
        t[now].xy+=(ll)T*t[now].x+(ll)S*t[now].y+(ll)(r-l+1)*S*T;        
        t[now].sqr+=(ll)2*S*t[now].x+(ll)S*S*(r-l+1);           
        t[now].x+=(ll)(r-l+1)*S, t[now].y+=(ll)(r-l+1)*T;            
    } 
    inline void mark2(int l,int r,int now,ll S,ll T) 
    {
        t[now].set_tag=1, t[now].set_s=S, t[now].set_t=T; 
        t[now].add_s=t[now].add_t=0;          
        t[now].x=sum[r]-sum[l-1]+(ll)S*(r-l+1); 
        t[now].y=sum[r]-sum[l-1]+(ll)T*(r-l+1);      
        t[now].xy=sqr[r]-sqr[l-1]+(ll)(T+S)*(sum[r]-sum[l-1])+(ll)(r-l+1)*S*T;  
        t[now].sqr=sqr[r]-sqr[l-1]+(ll)S*S*(r-l+1)+(ll)2*S*(sum[r]-sum[l-1]);              
    }
    inline void pushdown(int l,int r,int now) 
    {
        if(t[now].set_tag) 
        {
            int mid=(l+r)>>1; 
            if(l<=mid) mark2(l,mid,now<<1,t[now].set_s,t[now].set_t); 
            if(r>mid)  mark2(mid+1,r,now<<1|1,t[now].set_s,t[now].set_t);    
            t[now].set_s=t[now].set_t=t[now].set_tag=0;          
        }
        if(t[now].add_s || t[now].add_t) 
        {
            int mid=(l+r)>>1;   
            if(l<=mid) mark1(l,mid,now<<1,t[now].add_s,t[now].add_t);  
            if(r>mid) mark1(mid+1,r,now<<1|1,t[now].add_s,t[now].add_t);   
            t[now].add_t=t[now].add_s=0;        
        }           
    }
    void build(int l,int r,int now) 
    {
        if(l==r) 
        {
            t[now].x=X[l]; 
            t[now].y=Y[l]; 
            t[now].xy=(ll)X[l]*Y[l];      
            t[now].sqr=(ll)X[l]*X[l];     
            return;   
        } 
        int mid=(l+r)>>1;   
        if(mid>=l) build(l,mid,now<<1);  
        if(r>mid) build(mid+1,r,now<<1|1);         
        pushup(l,r,now);   
    }   
    // x+=S, y+=T     
    void addv(int l,int r,int now,int L,int R,double S,double T) 
    { 
        if(l>=L&&r<=R) 
        {
            mark1(l,r,now,S,T);  
            return;   
        }   
        pushdown(l,r,now);     
        int mid=(l+r)>>1; 
        if(L<=mid) addv(l,mid,now<<1,L,R,S,T); 
        if(R>mid) addv(mid+1,r,now<<1|1,L,R,S,T); 
        pushup(l,r,now);    
    }
    void setv(int l,int r,int now,int L,int R,double S,double T) 
    {
        if(l>=L&&r<=R) 
        {
            mark2(l,r,now,S,T); 
            return; 
        }
        pushdown(l,r,now); 
        int mid=(l+r)>>1;   
        if(L<=mid) setv(l,mid,now<<1,L,R,S,T); 
        if(R>mid) setv(mid+1,r,now<<1|1,L,R,S,T); 
        pushup(l,r,now);    
    }
    ll queryx(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return t[now].x;     
        pushdown(l,r,now);   
        ll re=0; 
        int mid=(l+r)>>1;   
        if(L<=mid) re+=queryx(l,mid,now<<1,L,R); 
        if(R>mid) re+=queryx(mid+1,r,now<<1|1,L,R); 
        return re;   
    }
    ll queryy(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return t[now].y;  
        pushdown(l,r,now);   
        ll re=0; 
        int mid=(l+r)>>1;  
        if(L<=mid) re+=queryy(l,mid,now<<1,L,R); 
        if(R>mid) re+=queryy(mid+1,r,now<<1|1,L,R); 
        return re;  
    }
    ll queryxy(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return t[now].xy;  
        pushdown(l,r,now);  
        ll re=0; 
        int mid=(l+r)>>1;  
        if(L<=mid) re+=queryxy(l,mid,now<<1,L,R); 
        if(R>mid) re+=queryxy(mid+1,r,now<<1|1,L,R);   
        return re;   
    } 
    ll queryxx(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return t[now].sqr;   
        pushdown(l,r,now); 
        ll re=0; 
        int mid=(l+r)>>1;  
        if(L<=mid) re+=queryxx(l,mid,now<<1,L,R); 
        if(R>mid) re+=queryxx(mid+1,r,now<<1|1,L,R); 
        return re;           
    } 
    int main() 
    {  
        int i,j,cas; 
        // setIO("de");      
        n=IO::rd(),Q=IO::rd(); 
        for(i=1;i<=n;++i) X[i]=IO::rd(); 
        for(i=1;i<=n;++i) Y[i]=IO::rd();    
        for(i=1;i<=n;++i) sum[i]=sum[i-1]+i, sqr[i]=sqr[i-1]+(ll)i*i;    
        build(1,n,1);  
        for(cas=1;cas<=Q;++cas) 
        {
            int opt,l,r,s,t; 
            opt=IO::rd(),l=IO::rd(),r=IO::rd();    
            if(opt==1) 
            {
                long double up, down;    
                long double ybar=queryy(1,n,1,l,r)/(double)(r-l+1);     
                long double xbar=queryx(1,n,1,l,r)/(double)(r-l+1);              
                up=(ldb)queryxy(1,n,1,l,r)-ybar*(ldb)queryx(1,n,1,l,r)-xbar*(ldb)queryy(1,n,1,l,r)+(ldb)(r-l+1)*xbar*ybar;
                down=(ldb)queryxx(1,n,1,l,r)+xbar*xbar*(ldb)(r-l+1)-2.00*xbar*(ldb)queryx(1,n,1,l,r);    
                long double answer=up/down; 
                printf("%.10lf
    ",(double)answer);     
            } 
            if(opt==2) 
            { 
                s=IO::rd(),t=IO::rd();   
                addv(1,n,1,l,r,s,t); 
            } 
            if(opt==3) 
            { 
                s=IO::rd(),t=IO::rd();      
                setv(1,n,1,l,r,s,t);           
            }  
        }           
        return 0;         
    }    
    /* 
    */
    

      

  • 相关阅读:
    基于visual Studio2013解决面试题之1101差值最小
    基于visual Studio2013解决面试题之1009兄弟字符串
    基于visual Studio2013解决面试题之1007鸡蛋和篮子
    基于visual Studio2013解决面试题之1006判断升序
    4.16 删除重复记录
    4.9 当相应行存在时更新
    4.8 在表中编辑记录
    4.7 阻止对某几列插入
    4.6 一次向多个表中插入记录
    4.4 从一个表向另外的表中复制行
  • 原文地址:https://www.cnblogs.com/guangheli/p/11384084.html
Copyright © 2020-2023  润新知