LuoguP3924 康娜的线段树 线段树+期望

秒了一个 70 pts 做法,满分做法无外乎是用前缀和来去掉一个 log. 

code: 

#include <bits/stdc++.h>    
#define N 1000009  
#define ll long long  
#define lson now<<1 
#define rson now<<1|1   
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
// 区间加 -> 线段树[l,r]区间,则贡献为[l,r]范围内所有节点 size*v,可以下传这个标记.      
int n,m;  
int lazy[N<<2],leaf[N<<2],len[N<<2];  
ll si[N<<2],sum[N<<2],sumv[N<<2];  
int A[N],dep[N<<2],maxdep; 
void build(int l,int r,int now) 
{ 
    len[now]=r-l+1;  
    if(l==r) return;        
    int mid=(l+r)>>1;    
    dep[lson]=dep[now]+1,dep[rson]=dep[now]+1;  
    build(l,mid,lson),build(mid+1,r,rson);  
}     
void pushup(int now) 
{  
    si[now]=si[lson]+si[rson]+1ll*len[now]*leaf[now];           
    sumv[now]=sumv[lson]+sumv[rson];       
    sum[now]=sum[lson]+sum[rson]+1ll*sumv[now]*leaf[now];            
}
void dfs(int l,int r,int now) 
{
    if(l==r) 
    {
        if(dep[now]==maxdep) si[now]=1,leaf[now]=1;     
        else si[now]=2,leaf[now]=2;  
        if(si[now]==1) sum[now]=A[l];  
        else sum[now]=A[l]*2;      
        sumv[now]=A[l];        
        return;      
    }     
    int mid=(l+r)>>1;    
    dfs(l,mid,lson),dfs(mid+1,r,rson);     
    leaf[now]=leaf[lson]+leaf[rson];  
    pushup(now); 
}
void mark(int now,ll v) 
{   
    lazy[now]+=(int)v;    
    sumv[now]+=1ll*v*len[now];     
    sum[now]+=1ll*v*si[now];          
}   
void pushdown(int now) 
{
    if(lazy[now]) 
    {
        mark(lson,lazy[now]); 
        mark(rson,lazy[now]);   
        lazy[now]=0;  
    }
}
void update(int l,int r,int now,int L,int R,ll v) 
{   
    if(l>=L&&r<=R) 
    {
        mark(now,v); 
        return; 
    }  
    int mid=(l+r)>>1; 
    pushdown(now);  
    if(L<=mid)  update(l,mid,lson,L,R,v);  
    if(R>mid)   update(mid+1,r,rson,L,R,v);   
    pushup(now);   
}   
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,flag=1;  char c;  
    do 
    {
        c=nc();  
        if(c=='-') flag=-1; 
    }while(c<48);  
    while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc();   
    return x*flag;     
} 
int main() 
{ 
    // setIO("input");                
    ll qaq; 
    n=rd(),m=rd(),qaq=(ll)rd(); 
    build(1,n,1);  
    for(int i=1;i<(N<<2);++i) maxdep=max(dep[i],maxdep);    
    for(int i=1;i<=n;++i) A[i]=rd(); 
    dfs(1,n,1);                
    ll dn=leaf[1];                                
    ll gcd=__gcd(dn,qaq);                    
    dn/=gcd,qaq/=gcd;      
    int x,y,z;           
    for(int i=1;i<=m;++i) 
    {  
        x=rd(),y=rd(),z=rd();  
        update(1,n,1,x,y,1ll*z);        
        ll tot=sum[1];                   
        printf("%lld\n",tot/dn*qaq);
    }    
    return 0; 
} 

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值