HDOJ.4578 Transformation (多种区间操作的线段树)

本文介绍了一种使用段式树处理区间加、区间乘、区间赋值和求解区间幂和(包括一阶、二阶和三阶幂和)的方法。详细解释了如何维护懒标记,处理各种操作之间的相互影响,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 题意 : 四种操作,1. 区间加,2. 区间乘,3. 区间更新为固定值,
    4.求区间\(p\)次方和,\(p\)取值\(1到3\)
  • 思路 : 维护前三种操作的懒标记,注意相互之间的影响.对询问,因为只有三种,直接对三种和都进行维护
#include<bits/stdc++.h>
#define ll long long 
#define FOR(i,l,r) for(int i = l ; i <= r ;++i ) 
#define inf 0x3f3f3f3f
#define EPS (1e-9)
#define ALL(T)  T.begin(),T.end()
#define lson(i)     i<<1
#define rson(i)     (i<<1|1)
#define sum(i,j)    seg[i].sum[j]
using namespace std; 
const int modp = 10007;
const int maxn = 1e6+50;

ll a[maxn];
ll ans = 0;
struct node{
    int l,r;
    ll val,add,mul;
    ll sum[3];
}seg[maxn*4];

inline void madd(ll &a,ll b){
    a = (a+b)%modp;
} 
inline void mmul(ll &a,ll b){
    a = (a*b)%modp;
}


inline void push_up(int p){
    sum(p,0) = (sum(lson(p),0) + sum(rson(p),0))%modp;
    sum(p,1) = (sum(lson(p),1) + sum(rson(p),1))%modp;
    sum(p,2) = (sum(lson(p),2) + sum(rson(p),2))%modp;
}

inline void push_down(int p){
    if(seg[p].val){ 
        seg[lson(p)].val = seg[p].val;
        seg[lson(p)].add = 0;
        seg[lson(p)].mul = 1;
        
        seg[rson(p)].val = seg[p].val;
        seg[rson(p)].add = 0;
        seg[rson(p)].mul = 1;
        
        ll len = seg[p].r - seg[p].l + 1 ;
        ll lsize = len - len/2 , rsize = len/2;
        
        sum(lson(p),0) = (seg[p].val * lsize)%modp;
        sum(rson(p),0) = (seg[p].val * rsize)%modp;
    
        ll qp = (seg[p].val*seg[p].val)%modp;
        sum(lson(p),1) = (qp * lsize)%modp;
        sum(rson(p),1) = (qp * rsize)%modp;
        qp = (qp*seg[p].val)%modp;
        sum(lson(p),2) = (qp * lsize)%modp;
        sum(rson(p),2) = (qp * rsize)%modp;
        
        seg[p].val = 0;
    }
    // 乘法标记
    if(seg[p].mul!=1){
        mmul(seg[lson(p)].mul,seg[p].mul);
        mmul(seg[rson(p)].mul,seg[p].mul);
    
        mmul(seg[lson(p)].add,seg[p].mul);
        mmul(seg[rson(p)].add,seg[p].mul);
        
        mmul(sum(lson(p),0),seg[p].mul);
        mmul(sum(rson(p),0),seg[p].mul);
        
        ll q = (seg[p].mul*seg[p].mul)%modp;
        mmul(sum(lson(p),1),q);
        mmul(sum(rson(p),1),q);
        
        mmul(q,seg[p].mul);
        mmul(sum(lson(p),2),q);
        mmul(sum(rson(p),2),q);
        
        seg[p].mul = 1;
    }
    // 加法标记
    if(seg[p].add){
        madd(seg[lson(p)].add,seg[p].add);
        madd(seg[rson(p)].add,seg[p].add);
        ll val = seg[p].add;
        ll len = seg[p].r - seg[p].l + 1 ;
        ll lsize = len - len/2 , rsize = len/2;
        ll q2 =(val*val)%modp,q3 = (q2*val)%modp;
        madd(sum(lson(p),2),
            (lsize*q3)%modp +   3 * val * ((sum(lson(p),1) + sum(lson(p),0)*val)%modp));
        madd(sum(rson(p),2),
            (rsize*q3)%modp +   3 * val * ((sum(rson(p),1) + sum(rson(p),0)*val)%modp));
        
        madd(sum(lson(p),1),(lsize*q2)%modp+2*(sum(lson(p),0)*val)%modp);
        madd(sum(rson(p),1),(rsize*q2)%modp+2*(sum(rson(p),0)*val)%modp);
    
        madd(sum(lson(p),0),(lsize*val));
        madd(sum(rson(p),0),(rsize*val));
        seg[p].add = 0;
    }
}

void build(int p,int l,int r){
    seg[p].l = l;
    seg[p].r = r;
    seg[p].add = 0;
    seg[p].mul = 1;
    seg[p].val = 0;
    seg[p].sum[0] = seg[p].sum[1] = seg[p].sum[2] = 0;
    if(l==r)    return;
    int mid = (l+r)>>1;
    build(lson(p),l,mid);
    build(rson(p),mid+1,r);
    push_up(p);
}
// 乘法操作
void mul(int i,int l,int r,ll val){
    if(seg[i].l >=l && seg[i].r <=r){
        // 直接更新当前区间
        mmul(seg[i].add,val);
        mmul(seg[i].mul,val);
        // 乘法 可以提取公因数
        mmul(sum(i,0),val);
        mmul(sum(i,1),(val*val)%modp);
        mmul(sum(i,2),(((val*val)%modp)*val)%modp);
        return ;
    }
    push_down(i);
    int mid = (seg[i].l + seg[i].r)>>1;
    if(l<=mid)  mul(lson(i),l,r,val);
    if(r>mid)   mul(rson(i),l,r,val);
    push_up(i);
}

// 加法操作
void add(int i,int l,int r,ll val){
    if(seg[i].l >=l && seg[i].r <=r){
        madd(seg[i].add,val);
        ll len = seg[i].r-seg[i].l+1;
        ll q2 = (val*val)%modp, q3 = (q2*val)%modp;
        
        madd(sum(i,2),q3*len+3*val*(sum(i,1)+sum(i,0)*val));
        madd(sum(i,1),(q2*len+2*(sum(i,0)*val)%modp)%modp);
        madd(sum(i,0),(len*val)%modp);
        return ;
    }
    push_down(i);
    int mid = (seg[i].l + seg[i].r)>>1;
    if(l<=mid)  add(lson(i),l,r,val);
    if(r>mid)   add(rson(i),l,r,val);
    push_up(i);
}

// 区间更新固定值
void cha(int i,int l,int r,ll val){
    if(seg[i].l >=l && seg[i].r <=r){
        ll len = seg[i].r - seg[i].l + 1 ; 
        seg[i].val = val;
        sum(i,0) = seg[i].val;
        mmul(sum(i,0),len);
        
        sum(i,1) = seg[i].val;
        mmul(sum(i,1),sum(i,1));
        mmul(sum(i,1),len);
        
        sum(i,2) = sum(i,1);
        mmul(sum(i,2),val);
        
        seg[i].add = 0;
        seg[i].mul = 1;
        return ;
    }
    push_down(i);
    int mid = (seg[i].l + seg[i].r)>>1;
    if(l<=mid)  cha(lson(i),l,r,val);
    if(r>mid)   cha(rson(i),l,r,val);
    push_up(i);
}

ll query(int i,int l,int r,ll val){
    ll res = 0;
    if(seg[i].l >= l &&  seg[i].r <= r){
        return sum(i,val-1);
    }   
    push_down(i);
    int mid = (seg[i].l+seg[i].r)>>1;
    if(l<=mid) madd(res,query(lson(i),l,r,val)) ;
    if(r>mid)  madd(res,query(rson(i),l,r,val));
    
    return res;
}
int n,m;
void solve(){
    build(1,1,n);
    ll op,x,y,z;
    FOR(i,1,m){
        scanf("%lld%lld%lld%lld",&op,&x,&y,&z); 
        switch(op){
            case 1: add(1,x,y,z);   break;
            case 2: mul(1,x,y,z);   break;
            case 3: cha(1,x,y,z);   break;
            case 4: printf("%lld\n",query(1,x,y,z)); 
        }
    }
    
}
int main(){
    while(cin >> n >> m){
        if(n==0 && m == 0)  break;
        solve();
    }
    return 0;
}

/*
6 9
3 2 6 10
1 1 2 6
1 2 2 1
2 6 6 7
4 1 2 3

10000 100
2 56 59 100
1 564 1254 10000
2 7 800 2
3 1 600 9999
4 5 10000 3
2 102 5645 9999
4 568 789 3
4 1 2 1
4 500 1000 1
4 500 1000 2
4 500 1000 3

附带数据^_^
*/

调bug调了一下午,这种长度的代码一定要理清思路在写,不然会越写越乱,bug百出QAQ狗屎代码就是恶心自己吧

  1. 区间加, 对其他两种操作没有影响
  2. 区间乘, 对区间加有影响,加法标记要乘上乘法标记
  3. 区间更新固定值, 区间加,乘都不在起作用,直接清零
  4. 区间和: \(\sum{a_i}\)
    • +d: \(\sum_l^r{(a_i+d)} = \sum_l^r{a_i}+(r-l+1)*d\)
    • *d: \(\sum{(a_i*d)} = d*\sum{a_i}\) 直接提取公因数
    • =d: 因为\(a_i = d\),所以\(\sum_l^r{a_i} = d*(r-l+1)\)
  5. 区间平方和: \(\sum{a_i^2}\)
    • +d: 展开和式,\(\sum_l^r(a_i+d)^2 = \sum{a_i^2}+2d\sum{a_i}+(r-l+1)*d^2\)
    • *d: \(\sum{(a_i*d)^2} = d^2*\sum{a_i^2}\) 直接提取公因数
    • =d: \(\sum_l^r{a_i^2} = d^2*(r-l+1)\)
  6. 区间立方和: \(\sum{a_i^3}\)
    • +d: 展开和式,\(\sum_l^r(a_i+d)^3 = \sum{a_i^3}+2d(\sum{a_i^2}+d*\sum{a_i})+(r-l+1)*d^3\)
    • *d: \(\sum{(a_i*d)^3} = d^3*\sum{a_i^3}\) 直接提取公因数
    • =d: \(\sum_l^r{a_i^3} = d^3*(r-l+1)\)

因为高次项要用到低次项,所以要先更新高次项.
=d时长度只用乘一次,写的时候没注意结果wa哭

转载于:https://www.cnblogs.com/xxrlz/p/11252195.html

内容概要:本文详细探讨了基于MATLAB/SIMULINK的多载波无线通信系统仿真及性能分析,重点研究了以OFDM为代表的多载波技术。文章首先介绍了OFDM的基本原理和系统组成,随后通过仿真平台分析了不同调制方式的抗干扰性能、信道估计算法对系统性能的影响以及同步技术的实现与分析。文中提供了详细的MATLAB代码实现,涵盖OFDM系统的基本仿真、信道估计算法比较、同步算法实现和不同调制方式的性能比较。此外,还讨论了信道特征、OFDM关键技术、信道估计、同步技术和系统级仿真架构,并提出了未来的改进方向,如深度学习增强、混合波形设计和硬件加速方案。; 适合人群:具备无线通信基础知识,尤其是对OFDM技术有一定了解的研究人员和技术人员;从事无线通信系统设计与开发的工程师;高校通信工程专业的高年级本科生和研究生。; 使用场景及目标:①理解OFDM系统的工作原理及其在多径信道环境下的性能表现;②掌握MATLAB/SIMULINK在无线通信系统仿真中的应用;③评估不同调制方式、信道估计算法和同步算法的优劣;④为实际OFDM系统的设计和优化提供理论依据和技术支持。; 其他说明:本文不仅提供了详细的理论分析,还附带了大量的MATLAB代码示例,便于读者动手实践。建议读者在学习过程中结合代码进行调试和实验,以加深对OFDM技术的理解。此外,文中还涉及了一些最新的研究方向和技术趋势,如AI增强和毫米波通信,为读者提供了更广阔的视野。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值