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

本文介绍了一种利用线段树进行动态区间操作的方法,通过实例详细讲解了如何在线段树上实现区间加法、区间赋值及查询操作,并提供了一段完整的C++代码实现,展示了该方法在解决特定问题上的高效性和灵活性。

考试的时候切掉了,然而卡精 + 有一个地方忘开 $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\n",(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;         
}    
/* 
*/

  

内容概要:本文提出了一种基于融合鱼鹰算法和柯西变异的改进麻雀优化算法(OCSSA),用于优化变分模态分解(VMD)的参数,进而结合卷积神经网络(CNN)与双向长短期记忆网络(BiLSTM)构建OCSSA-VMD-CNN-BILSTM模型,实现对轴承故障的高【轴承故障诊断】基于融合鱼鹰和柯西变异的麻雀优化算法OCSSA-VMD-CNN-BILSTM轴承诊断研究【西储大学数据】(Matlab代码实现)度诊断。研究采用西储大学公开的轴承故障数据集进行实验验证,通过优化VMD的模态数和惩罚因子,有效提升了信号分解的准确性与稳定性,随后利用CNN提取故障特征,BiLSTM捕捉时间序列的深层依赖关系,最终实现故障类型的智能识别。该方法在提升故障诊断度与鲁棒性方面表现出优越性能。; 适合人群:具备一定信号处理、机器学习基础,从事机械故障诊断、智能运维、工业大数据分析等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①解决传统VMD参数依赖人工经验选取的问题,实现参数自适应优化;②提升复杂工况下滚动轴承早期故障的识别准确率;③为智能制造与预测性维护提供可靠的技术支持。; 阅读建议:建议读者结合Matlab代码实现过程,深入理解OCSSA优化机制、VMD信号分解流程以及CNN-BiLSTM网络架构的设计逻辑,重点关注参数优化与故障分类的联动关系,并可通过更换数据集进一步验证模型泛化能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值