• hiho #1078 : 线段树的区间修改


    题意:长度为n的序列上有两种操作

    0 ql qr  输出区间[ql,qr]和

    1 ql qr v 区间[ql,qr]赋值为v

    线段树懒标基础题,我用分块写了一个,在本题数据竟然跑的飞快

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=1e5+5;
    typedef long long ll;
    
    int val[maxn],belong[maxn],l[maxn],r[maxn],inv[maxn];
    ll ans[maxn];
    int n,q,op,ql,qr,v,cnt,block;
    
    void update(int L,int R,int bt){
        if(L==l[bt]&&R==r[bt]){
    	inv[bt]=v;ans[bt]=(ll)v*(R-L+1);
    	return ;
        }
        if(inv[bt]){
          rep(i,l[bt],L-1)val[i]=inv[bt];
          rep(i,R+1,r[bt])val[i]=inv[bt];
          rep(i,L,R)ans[bt]+=v-inv[bt],val[i]=v;
          inv[bt]=0;
          return ;
        }
        rep(i,L,R)ans[bt]+=v-val[i],val[i]=v;
    }
    
    void update(){
        int b1=belong[ql],b2=belong[qr];
        if(b1==b2)update(ql,qr,b1);
        else{
    	update(ql,r[b1],b1);b1++;
    	while(b1<b2)
    	  update(l[b1],r[b1],b1),b1++;
    	update(l[b2],qr,b2);
        }
    }
    
    ll query(int L,int R,int bt){
        if(l[bt]==L&&r[bt]==R)return ans[bt];
        if(inv[bt])return (ll)inv[bt]*(R-L+1);
        ll res=0;
        rep(i,L,R)res+=val[i];
        return res;
    }
    
    ll query(){
        ll res=0;
        int b1=belong[ql],b2=belong[qr];
        if(b1==b2)return query(ql,qr,b1);
        res+=query(ql,r[b1],b1);b1++;
        while(b1<b2)res+=ans[b1++];
        res+=query(l[b2],qr,b2);
        return res;
    }
    
    void init(){
        block=sqrt(n);cnt=n/block;
        rep(i,0,n-1){
    	belong[i]=i/block;
    	ans[belong[i]]+=val[i];
        }
        rep(i,0,cnt-1)l[i]=i*block,r[i]=(i+1)*block-1;
        if(n%block){
    	l[cnt]=cnt*block,r[cnt]=n-1;cnt++;
        }
    }
    
    int main(){
        scanf("%d",&n);
        rep(i,0,n-1)scanf("%d",val+i);
        init();
        scanf("%d",&q);
        while(q--){
    	scanf("%d%d%d",&op,&ql,&qr);
    	ql--;qr--;
    	if(op){
    	    scanf("%d",&v);
    	    update();
    	}
    	else
    	    printf("%lld
    ",query());
        }
      
        return 0;
    }
    
  • 相关阅读:
    推销
    5132. 颜色交替的最短路径
    5130. 等价多米诺骨牌对的数量
    @babel/plugin-transform-runtime和@babel/preset-env的区别
    5128. 最深叶节点的最近公共祖先(二叉树)
    1094. 拼车
    1109. 航班预订统计(数组)
    5129. 表现良好的最长时间段(数组)
    path.resove 和 path.join
    【原生】 call、apply、bind 的基本使用方法,已经解析了某些源码
  • 原文地址:https://www.cnblogs.com/jihe/p/6945108.html
Copyright © 2020-2023  润新知