Naive Operations (线段树 分析复杂度)

Posted 昵称很长很长真是太好了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Naive Operations (线段树 分析复杂度)相关的知识,希望对你有一定的参考价值。

题目:
给出一个长度为n初值为0的数组,以及长度为n的b数组,然后q次操作,add(l,r) 使得区间l-r所有元素+1,或者查询l~r区间a[i]/b[i]的和
题解:
很少情况下能很快写出一道线段树题目,关键还0调试
首先题目说了b是个排列,突破点也就是b这个条件。
因为题目是向下取整,那么假设b[1]=100000,那么你对他修改99999次都是没有任何影响的,那岂不是可以不去修改这个点。同理考虑其他的节点,发现b[i]越大,那么a[i]/b[j]如果变大的话,需要修改的次数也会越多。
我们计算一下这个次数
级别是一个1e6的级别,nlogn可以过。

那么我们用一个 i m i n i imin_i imini表示你还需要对 a i a_i ai加几次,才会使得 a i / b i a_i/b_i ai/bi增大1.
如果imin用最小值去维护区间,每次区间加的时候如果发现区间最小值为1,那么递归下去修改贡献,否则直接懒标记把区间最小值-1。

代码:

#include<bits/stdc++.h>
using namespace std;
#define endl '\\n'
#define int long long
const int maxn = 1e5 + 10;
const int mod=998244353;

int b[maxn];
int imin[maxn<<2],sum[maxn<<2],lazy[maxn<<2];

void push_up(int node)
    imin[node]=min(imin[node<<1],imin[node<<1|1]);
    sum[node]=sum[node<<1]+sum[node<<1|1];


void build(int node,int start,int ends)
    lazy[node]=0;
    if(start==ends)
        sum[node]=0;
        imin[node]=b[start];
        return ;
    
    int mid=(start+ends)>>1;
    build(node<<1,start,mid);
    build(node<<1|1,mid+1,ends);
    push_up(node);


void push_down(int node)
    if(lazy[node])
        lazy[node<<1]+=lazy[node];
        lazy[node<<1|1]+=lazy[node];
        imin[node<<1]-=lazy[node];
        imin[node<<1|1]-=lazy[node];
    
    lazy[node]=0;


void update(int node,int start,int ends,int l,int r)
    if(start==ends)
        if(imin[node]==1)
            imin[node]=b[start];
            sum[node]++;
        
        else imin[node]--;
        return ;
    
    if(l<=start&&ends<=r&&imin[node]!=1)
        lazy[node]+=1;
        imin[node]--;
        return ;
    
    push_down(node);
    int mid=start+ends>>1;
    if(l<=mid) update(node<<1,start,mid,l,r);
    if(mid<r) update(node<<1|1,mid+1,ends,l,r);
    push_up(node);


int query(int node,int start,int ends,int l,int r)
    if(l<=start&&ends<=r)
        return sum[node];
    
    int mid=start+ends>>1;
    push_down(node);
    int res=0;
    if(l<=mid) res+=query(node<<1,start,mid,l,r);
    if(mid<r) res+=query(node<<1|1,mid+1,ends,l,r);
    return res;


signed main()
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,q;

    while(cin>>n>>q)
        for(int i=1;i<=n;i++) cin>>b[i];
        build(1,1,n);
        while(q--)
            string s;
            cin>>s;
            if(s[0]=='a')
                int x,y;
                cin>>x>>y;
                update(1,1,n,x,y);
            
            else
                int x,y;
                cin>>x>>y;
                int ans=query(1,1,n,x,y);
                cout<<ans<<endl;
            
        
    



以上是关于Naive Operations (线段树 分析复杂度)的主要内容,如果未能解决你的问题,请参考以下文章

Naive Operations (线段树 分析复杂度)

HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)

HDU 6351 Naive Operations(线段树)

HDU - 6315 Naive Operations (线段树+思维) 2018 Multi-University Training Contest 2

[HDU6315]Naive Operations(线段树+树状数组)

HDU6315 Naive Operations(多校第二场1007)(线段树)