BZOJ 4821 [Sdoi2017]相关分析 ——线段树

打开题面,看到许多$sum$

woc,好神啊,SDOI好强啊

然后展开之后,woc,SDOI好弱啊,怎么T3出个线段树裸题啊。

最后写代码的时候,woc,SDOI怎么出个这么码农的题啊,怎么调啊。

想想自己加上考场$Debuff$是肯定写不出来的。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
//#define double long double
#define ll long long
#define mp make_pair
#define maxn 400005
 
#define sum(x) (1LL*(x)*((x)+1)/2)
#define sum2(x) (1LL*(x)*((x)+1)*(2*(x)+1)/6)
 
double sum_x[maxn],sum_y[maxn],sum_xy[maxn],sum_xx[maxn];
double tag_x[maxn],tag_y[maxn];
bool tag_c[maxn];
int x[maxn],y[maxn];
double sumx,sumy,sumxy,sumxx;
 
int n,m;
 
void update(int o,int l,int r)
{
    sum_x[o]=sum_x[o<<1]+sum_x[o<<1|1];
    sum_y[o]=sum_y[o<<1]+sum_y[o<<1|1];
    sum_xy[o]=sum_xy[o<<1]+sum_xy[o<<1|1];
    sum_xx[o]=sum_xx[o<<1]+sum_xx[o<<1|1];
}
 
void add_tag_x(int o,int l,int r,double s)
{
    tag_x[o]+=s;
    sum_xx[o]+=1LL*s*s*(r-l+1)+2*s*sum_x[o];
    sum_xy[o]+=1LL*sum_y[o]*s;
    sum_x[o]+=1LL*(r-l+1)*s;
}
 
void add_tag_y(int o,int l,int r,double t)
{
    tag_y[o]+=t;
    sum_xy[o]+=1LL*sum_x[o]*t;
    sum_y[o]+=1LL*(r-l+1)*t;
}
 
void add_cov(int o,int l,int r)
{
    sum_y[o]=sum_x[o]=sum(r)-sum(l-1);
    sum_xy[o]=sum_xx[o]=sum2(r)-sum2(l-1);
    tag_x[o]=tag_y[o]=0; tag_c[o]=true;
}
 
void pushdown(int o,int l,int r)
{
    if (o==0||l==r) return;
    int mid=l+r>>1;
    if (tag_c[o])
    {
        add_cov(o<<1,l,mid);
        add_cov(o<<1|1,mid+1,r);
        tag_c[o]=false;
    }
    if (tag_x[o])
    {
        add_tag_x(o<<1,l,mid,tag_x[o]);
        add_tag_x(o<<1|1,mid+1,r,tag_x[o]);
        tag_x[o]=0; 
    }
    if (tag_y[o])
    {
        add_tag_y(o<<1,l,mid,tag_y[o]);
        add_tag_y(o<<1|1,mid+1,r,tag_y[o]);
        tag_y[o]=0;
    }
}
 
void st_modify(int o,int l,int r,int L,int R,double s,double t)
{
    if (L<=l&&r<=R){add_tag_x(o,l,r,s);add_tag_y(o,l,r,t);return;}
    int mid=l+r>>1; pushdown(o,l,r);
    if (L<=mid) st_modify(o<<1,l,mid,L,R,s,t);
    if (R>mid) st_modify(o<<1|1,mid+1,r,L,R,s,t);
    update(o,l,r);
}
 
void modify(int l,int r,double s,double t)
{st_modify(1,1,n,l,r,s,t);}
 
void st_cov(int o,int l,int r,int L,int R)
{
    if (L<=l&&r<=R){add_cov(o,l,r);return;}
    int mid=l+r>>1; pushdown(o,l,r);
    if (L<=mid) st_cov(o<<1,l,mid,L,R);
    if (R>mid) st_cov(o<<1|1,mid+1,r,L,R);
    update(o,l,r);
}
 
void cover(int l,int r)
{st_cov(1,1,n,l,r);}
 
void st_query(int o,int l,int r,int L,int R)
{
    if (L<=l&&r<=R){sumx+=sum_x[o],sumy+=sum_y[o],sumxx+=sum_xx[o];sumxy+=sum_xy[o];return;}
    int mid=l+r>>1; pushdown(o,l,r);
    if (R<=mid) st_query(o<<1,l,mid,L,R);
    else if (L>mid) st_query(o<<1|1,mid+1,r,L,R);
    else st_query(o<<1,l,mid,L,R),st_query(o<<1|1,mid+1,r,L,R);
}
 
double query(int l,int r)
{
    sumx=0; sumy=0;sumxx=0; sumxy=0;
    double len=r-l+1; st_query(1,1,n,l,r);
    printf("%.10lf
",(len*sumxy-sumx*sumy)/(len*sumxx-sumx*sumx));
}
 
void build(int o,int l,int r)
{
    if (l==r)
    {
        sum_x[o]=x[l]; sum_y[o]=y[l];
        sum_xy[o]=1LL*x[l]*y[l]; sum_xx[o]=1LL*x[l]*x[l];
        return ;
    }
    int mid=l+r>>1;
    build(o<<1,l,mid);
    build(o<<1|1,mid+1,r);
    update(o,l,r);
}
 
int main()
{
    scanf("%d%d",&n,&m);
    F(i,1,n) scanf("%d",&x[i]);
    F(i,1,n) scanf("%d",&y[i]);
    build(1,1,n);
    F(i,1,m)
    {
        int opt,l,r,s,t;
        scanf("%d",&opt);
        switch(opt)
        {
            case 1:
                scanf("%d%d",&l,&r);
                query(l,r);
            break;
            case 2:
                scanf("%d%d%d%d",&l,&r,&s,&t);
                modify(l,r,(double)s,(double)t);
            break;
            case 3:
                scanf("%d%d%d%d",&l,&r,&s,&t);
                cover(l,r);
                modify(l,r,(double)s,(double)t);
        }
    }
}

  

原文地址:https://www.cnblogs.com/SfailSth/p/6737664.html