ZKW 写法,DEBUG 1h 成功 401ms 最优解
  • 板块P1471 方差
  • 楼主Aurie
  • 当前回复0
  • 已保存回复0
  • 发布时间2025/2/5 14:29
  • 上次更新2025/2/5 17:21:09
查看原帖
ZKW 写法,DEBUG 1h 成功 401ms 最优解
999244
Aurie楼主2025/2/5 14:29

这题用 ZKW 线段树的永久懒标记写挺抽象的。

#include<bits/stdc++.h>
#define putchar putchar_unlocked
#define getchar getchar_unlocked
using namespace std;
template<typename T>
void read(T &x){x=0;char ch=getchar();while(!isdigit(ch)){ch=getchar();}while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}}
template<typename T>
void print(const T &x){if(x>9){print(x/10);}putchar(x%10|0x30);}
template<typename T>
void printcs(const T &x){if(x<0){putchar('-');print(-x);}else{print(x);}putchar(' ');}
template<typename T>
void println(const T &x){if(x<0){putchar('-');print(-x);}else{print(x);}putchar('\n');}
const int N = 1e5+10;
typedef double Type;

struct node{
    Type v,vv,tag;
}tr[N<<4];
int m;

inline void build(const int &n){
    for(m=1;m<=n;m<<=1);
    for(int i = m+1;i<=m+n;++i)scanf("%lf",&tr[i].v),tr[i].vv = tr[i].v*tr[i].v;
    for(int i = m-1;i;--i)tr[i].v=tr[i<<1].v+tr[i<<1|1].v,tr[i].vv = tr[i<<1].vv+tr[i<<1|1].vv;
}

inline void add(int l,int r,const Type &v){
    Type lres=0,rres=0;
    int lm=0,rm=0,now=1;
    for(l+=m-1,r+=m+1;l^r^1;l>>=1,r>>=1,now<<=1){
        lres+=lm*tr[l].tag;
        rres+=rm*tr[r].tag;

        tr[l].vv+=v*(v*lm+2*lres);
        tr[r].vv+=v*(v*rm+2*rres);
        
        tr[l].v+=v*lm;
        tr[r].v+=v*rm;
        
        if(~l&1)lres+=tr[l^1].v,tr[l^1].tag+=v,tr[l^1].vv+=v*(v*now+2*tr[l^1].v),tr[l^1].v+=v*now,lm+=now;
        if(r&1)rres+=tr[r^1].v,tr[r^1].tag+=v,tr[r^1].vv+=v*(v*now+2*tr[r^1].v),tr[r^1].v+=v*now,rm+=now;
    }
    lres+=lm*tr[l].tag;
    rres+=rm*tr[r].tag;
    tr[l].vv+=v*(v*lm+2*lres);
    tr[r].vv+=v*(v*rm+2*rres);

    tr[l].v+=v*lm;
    tr[r].v+=v*rm;
    lm+=rm;
    lres+=rres;
    l>>=1;
    for(;l;l>>=1){
        lres+=tr[l].tag*lm;
        tr[l].v+=v*lm;
        tr[l].vv+=v*(v*lm+2*lres);
        
    }
}


inline Type query(int l,int r){
    Type res = 0;
    int lm=0,rm=0,now=1;
    
    for(l+=m-1,r+=m+1;l^r^1;l>>=1,r>>=1,now<<=1){
        res+=tr[l].tag*lm+tr[r].tag*rm;
        if(~l&1)res+=tr[l^1].v,lm+=now;
        if(r&1)res+=tr[r^1].v,rm+=now;
    }
    res+=tr[l].tag*lm+tr[r].tag*rm;
    l>>=1;
    lm+=rm;
    for(;l;l>>=1){
        res+=tr[l].tag*lm;
    }
    return res;
}

inline Type queryt(int l,int r){
    Type lres=0,rres=0,res=0;
    int lm = 0,rm = 0,now = 1;
    for(l+=m-1,r+=m+1;l^r^1;l>>=1,r>>=1,now<<=1){
        res+=tr[l].tag*tr[l].tag*lm+tr[r].tag*tr[r].tag*rm+2*(tr[l].tag*lres+tr[r].tag*rres);
        lres+=tr[l].tag*lm;
        rres+=tr[r].tag*rm;
        if(~l&1)lres+=tr[l^1].v,res+=tr[l^1].vv,lm+=now;
        if(r&1)rres+=tr[r^1].v,res+=tr[r^1].vv,rm+=now;
    }
    res+=tr[l].tag*tr[l].tag*lm+tr[r].tag*tr[r].tag*rm+2*(tr[l].tag*lres+tr[r].tag*rres);
    l>>=1;
    lm+=rm;
    lres+=rres+tr[l].tag*lm+tr[r].tag*rm;
    for(;l;l>>=1){
        res+=tr[l].tag*(lm+2*lres);
        lres+=tr[l].tag*lm;
    }
    return res;
}
inline void printd(double ans){//浮点数输出优化!
    if(ans<0)ans=-ans,putchar('-');
    ans+=0.00005;
    print((int)ans);
    putchar('.');
    int res = (ans-(int)ans)*10000;
    if(res==0){
        puts("0000");
        return;
    }else if(res<10){
        putchar('0');putchar('0');putchar('0');
    }else if(res<100){
        putchar('0');putchar('0');
    }else if(res<1000){
        putchar('0');
    }
    println(res);
}
int main(){
    int n,q;
    read(n);
    read(q);
    build(n);
    int op,x,y;
    Type v;
    while(q--){
        read(op);
        read(x);
        read(y);
        switch(op){
            case 1:
            scanf("%lf",&v);
            add(x,y,v);     
            break;
            case 2:

            printd(query(x,y)/(y-x+1));
            break;
            default:
            double eva = query(x,y);
            eva*=eva/(y-x+1);
            printd((queryt(x,y)-eva)/(y-x+1));
            break;
        }
    }
    return 0;
}
2025/2/5 14:29
加载中...