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 (线段树 分析复杂度)的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)
HDU 6351 Naive Operations(线段树)
HDU - 6315 Naive Operations (线段树+思维) 2018 Multi-University Training Contest 2