0% found this document useful (0 votes)
11 views

Segment Tree

The document discusses various range query and update problems on arrays that can be solved efficiently using segment trees, including range sum, maximum, minimum, gcd and frequency queries as well as point updates. It also discusses extensions like lazy propagation for range addition queries.

Uploaded by

mukesh kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Segment Tree

The document discusses various range query and update problems on arrays that can be solved efficiently using segment trees, including range sum, maximum, minimum, gcd and frequency queries as well as point updates. It also discusses extensions like lazy propagation for range addition queries.

Uploaded by

mukesh kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 17

Range Sum Query and Point Update

const int N=1e6+10;


int t[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr) {
t[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=t[v*2]+t[v*2+1];
}
}

int query(int v,int tl,int tr,int l,int r){


if(l>r){
return 0;
}
if(l==tl&&r==tr){
return t[v];
}
int tm=(tl+tr)/2;
return query(v*2,tl,tm,l,min(r,tm))+query(v*2+1,tm+1,tr,max(l,tm+1),r);
}

void update(int v,int tl,int tr,int pos,int new_val){


if(tl==tr){
t[v]=new_val;
}else{
int tm=(tl+tr)/2;
if(pos<=tm){
update(v*2,tl,tm,pos,new_val);
}else{
update(v*2+1,tm+1,tr,pos,new_val);
}
t[v]=t[v*2]+t[v*2+1];
}
}

Searching for an array prefix with a given amount

int find_kth(int v,int tl,int tr,int k){


if(k>t[v]){
return -1;
}
if(tl==tr){
return tl;
}
int tm=(tl+tr)/2;
if(t[v*2]>=k){
return find_kth(v*2,tl,tm,k);
}else{
return find_kth(v*2+1,tm+1,tr,k-t[v*2]);
}
}

finding the kth zero

const int N=1e6+10;


int t[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr) {
t[v]=a[tl]==0;
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=t[v*2]+t[v*2+1];
}
}

int query(int v,int tl,int tr,int l,int r){


if(l>r){
return 0;
}
if(l==tl&&r==tr){
return t[v];
}
int tm=(tl+tr)/2;
return query(v*2,tl,tm,l,min(r,tm))+query(v*2+1,tm+1,tr,max(l,tm+1),r);
}

void update(int v,int tl,int tr,int pos,int new_val){


if(tl==tr){
t[v]=new_val==0;
}else{
int tm=(tl+tr)/2;
if(pos<=tm){
update(v*2,tl,tm,pos,new_val);
}else{
update(v*2+1,tm+1,tr,pos,new_val);
}
t[v]=t[v*2]+t[v*2+1];
}
}

int find_kth(int v,int tl,int tr,int k){


if(k>t[v]){
return -1;
}
if(tl==tr){
return tl;
}
int tm=(tl+tr)/2;
if(t[v*2]>=k){
return find_kth(v*2,tl,tm,k);
}else{
return find_kth(v*2+1,tm+1,tr,k-t[v*2]);
}
}

Range Maximum Query and Point Update

const int N=1e6+10;


int t[4*N];
void build(vector<int> &a,int v,int tl,int tr){
if(tl==tr) {
t[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=max(t[v*2],t[v*2+1]);
}
}

int query(int v,int tl,int tr,int l,int r){


if(l>r){
return INT_MIN;
}
if(l==tl&&r==tr){
return t[v];
}
int tm=(tl+tr)/2;
return max(query(v*2,tl,tm,l,min(r,tm)),query(v*2+1,tm+1,tr,max(l,tm+1),r));
}

void update(int v,int tl,int tr,int pos,int new_val){


if(tl==tr){
t[v]=new_val;
}else{
int tm=(tl+tr)/2;
if(pos<=tm){
update(v*2,tl,tm,pos,new_val);
}else{
update(v*2+1,tm+1,tr,pos,new_val);
}
t[v]=max(t[v*2],t[v*2+1]);
}
}

Searching for the first element atleast a given amount

int find_first(int v,int tl,int tr,int l,int r,int x){


if(tl>r||tr<l){
return -1;
}
if(l<=tl&&tr<=r){
if(t[v]<x){
return -1;
}
while(tl!=tr){
int mid=tl+(tr-tl)/2;
if(t[2*v]>=x){
v=2*v;
tr=mid;
}else{
v=2*v+1;
tl=mid+1;
}
}
return tl;
}
int mid=tl+(tr-tl)/2;
int rs=find_first(2*v,tl,mid,l,r,x);
if(rs!=-1){
return rs;
}
return find_first(2*v+1,mid+1,tr,l,r,x);
}

Range Maximum Query And number of times it appears

const int N=1e6+10;


pair<int, int> t[4*N];

pair<int,int> combine(pair<int,int> a,pair<int,int> b){


if(a.first>b.first){
return a;
}
if(b.first>a.first){
return b;
}
return make_pair(a.first,a.second+b.second);
}

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr){
t[v]=make_pair(a[tl],1);
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=combine(t[v*2],t[v*2+1]);
}
}

pair<int, int> query(int v,int tl,int tr,int l,int r){


if(l>r){
return make_pair(INT_MIN,0);
}
if(l==tl&&r==tr){
return t[v];
}
int tm=(tl+tr)/2;
return
combine(query(v*2,tl,tm,l,min(r,tm)),query(v*2+1,tm+1,tr,max(l,tm+1),r));
}

void update(int v,int tl,int tr,int pos,int new_val){


if(tl==tr){
t[v]=make_pair(new_val,1);
}else{
int tm=(tl+tr)/2;
if(pos<=tm){
update(v*2,tl,tm,pos,new_val);
}else{
update(v*2+1,tm+1,tr,pos,new_val);
}
t[v]=combine(t[v*2],t[v*2+1]);
}
}

Range GCD Query and Point Update

const int N=1e6+10;


int t[4*N];
void build(vector<int> &a,int v,int tl,int tr){
if(tl==tr) {
t[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=__gcd(t[v*2],t[v*2+1]);
}
}

int query(int v,int tl,int tr,int l,int r){


if(l>r){
return 0;
}
if(l==tl&&r==tr){
return t[v];
}
int tm=(tl+tr)/2;
return __gcd(query(v*2,tl,tm,l,min(r,tm)),query(v*2+1,tm+1,tr,max(l,tm+1),r));
}

void update(int v,int tl,int tr,int pos,int new_val){


if(tl==tr){
t[v]=new_val;
}else{
int tm=(tl+tr)/2;
if(pos<=tm){
update(v*2,tl,tm,pos,new_val);
}else{
update(v*2+1,tm+1,tr,pos,new_val);
}
t[v]=__gcd(t[v*2],t[v*2+1]);
}
}

Find the smallest number greater or equal to a specified number.

const int N=1e6+10;


multiset<int> t[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr){
t[v].insert(a[tl]);
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
for(auto &it:t[v*2]){
t[v].insert(it);
}
for(auto &it:t[v*2+1]){
t[v].insert(it);
}
}
}

int query(int v,int tl,int tr,int l,int r,int x){


if(l>r){
return INT_MAX;
}
if(l==tl&&r==tr){
auto pos=t[v].lower_bound(x);
if(pos!=t[v].end()){
return *pos;
}
return INT_MAX;
}
int tm=(tl+tr)/2;
return
min(query(v*2,tl,tm,l,min(r,tm),x),query(v*2+1,tm+1,tr,max(l,tm+1),r,x));
}

void update(vector<int> &a,int v,int tl,int tr,int pos,int new_val){


t[v].erase(t[v].find(a[pos]));
t[v].insert(new_val);
if(tl!=tr){
int tm=(tl+tr)/2;
if(pos<=tm){
update(a,v*2,tl,tm,pos,new_val);
}else{
update(a,v*2+1,tm+1,tr,pos,new_val);
}
}else{
a[pos]=new_val;
}
}
Range frequency query and point update

const int N=1e5+10;


unordered_map<int,int> t[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr){
t[v][a[tl]]++;
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
for(auto &it:t[v*2]){
t[v][it.first]+=it.second;
}
for(auto &it:t[v*2+1]){
t[v][it.first]+=it.second;
}
}
}

int query(int v,int tl,int tr,int l,int r,int x){


if(l>r){
return 0;
}
if(l==tl&&r==tr){
int cnt=t[v][x];
if(cnt==0){
t[v].erase(x);
}
return cnt;
}
int tm=(tl+tr)/2;
return query(v*2,tl,tm,l,min(r,tm),x)+query(v*2+1,tm+1,tr,max(l,tm+1),r,x);
}

void update(vector<int> &a,int v,int tl,int tr,int pos,int new_val){


t[v][a[pos]]--;
if(t[v][a[pos]]==0){
t[v].erase(a[pos]);
}
t[v][new_val]++;
if(tl!=tr){
int tm=(tl+tr)/2;
if(pos<=tm){
update(a,v*2,tl,tm,pos,new_val);
}else{
update(a,v*2+1,tm+1,tr,pos,new_val);
}
}else{
a[pos]=new_val;
}
}

Segment Tree Lazy Propogation

Range Addition and Point Query

const int N=1e6+10;


int t[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr){
t[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=0;
}
}

void update(int v,int tl,int tr,int l,int r,int add){


if(l>r){
return;
}
if(l==tl&&r==tr){
t[v]+=add;
}else{
int tm=(tl+tr)/2;
update(v*2,tl,tm,l,min(r,tm),add);
update(v*2+1,tm+1,tr,max(l,tm+1),r,add);
}
}

int query(int v,int tl,int tr,int pos){


if(tl==tr){
return t[v];
}
int tm=(tl+tr)/2;
if(pos<=tm){
return t[v]+query(v*2,tl,tm,pos);
}else{
return t[v]+query(v*2+1,tm+1,tr,pos);
}
}
Range Addition and Range Maximum Query

const int N=1e6+10;


int t[4*N];
int lazy[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr) {
t[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=max(t[v*2],t[v*2+1]);
}
}

void update(int v,int tl,int tr,int l,int r,int addend){


if(l>r){
return;
}
if(l==tl&&tr==r){
t[v]+=addend;
lazy[v]+=addend;
}else{
t[v*2]+=lazy[v];
lazy[v*2]+=lazy[v];
t[v*2+1]+=lazy[v];
lazy[v*2+1]+=lazy[v];
lazy[v]=0;
int tm=(tl+tr)/2;
update(v*2,tl,tm,l,min(r,tm),addend);
update(v*2+1,tm+1,tr,max(l,tm+1),r,addend);
t[v]=max(t[v*2],t[v*2+1]);
}
}

int query(int v,int tl,int tr,int l,int r){


if(l>r){
return INT_MIN;
}
if(l==tl&&tr==r){
return t[v];
}
t[v*2]+=lazy[v];
lazy[v*2]+=lazy[v];
t[v*2+1]+=lazy[v];
lazy[v*2+1]+=lazy[v];
lazy[v]=0;
int tm=(tl+tr)/2;
return max(query(v*2,tl,tm,l,min(r,tm)),query(v*2+1,tm+1,tr,max(l,tm+1),r));
}
Range Addition and Range Sum Query

const ll N=1e6+7;
ll seg[4*N];
ll lazy[4*N];
bool marked[4*N];

void build(vector<ll> &a,ll v,ll tl,ll tr){


if(tl==tr){
seg[v]=a[tl];
}else{
ll tm=(tl+tr)/2;
build(a,2*v,tl,tm);
build(a,v*2+1,tm+1,tr);
seg[v]=seg[2*v]+seg[2*v+1];
}
}

void update(ll v,ll tl,ll tr,ll l,ll r,ll addend){


if(marked[v]==true){
seg[v]+=(tr-tl+1)*lazy[v];
if(tl!=tr){
lazy[2*v]+=lazy[v];
lazy[2*v+1]+=lazy[v];
marked[2*v]=marked[2*v+1]=true;
}
lazy[v]=0;
marked[v]=false;
}
if(r<tl || l>tr || tl>tr){
return;
}
if(tl>=l && tr<=r){
seg[v]+=(tr-tl+1)*addend;
if(tl!=tr){
lazy[2*v]+=addend;
lazy[2*v+1]+=addend;
marked[2*v]=marked[2*v+1]=true;
}
return;
}
ll tm=(tl+tr)/2;
update(v*2,tl,tm,l,r,addend);
update(v*2+1,tm+1,tr,l,r,addend);
seg[v]=seg[2*v]+seg[2*v+1];
}

ll query(ll v,ll tl,ll tr,ll l,ll r){


if(marked[v]==true){
seg[v]+=(tr-tl+1)*lazy[v];
if(tl!=tr){
lazy[2*v]+=lazy[v];
lazy[2*v+1]+=lazy[v];
marked[2*v]=marked[2*v+1]=true;
}
lazy[v]=0;
marked[v]=false;
}
if(r<tl || l>tr || tl>tr){
return 0;
}
if(tl>=l && tr<=r){
return seg[v];
}
ll tm=(tl+tr)/2;
return query(2*v,tl,tm,l,r)+query(2*v+1,tm+1,tr,l,r);
}

Range Assignment and Point Query

const int N=1e6+10;


int marked[4*N];
int t[4*N];

void build(vector<int> &a,int v,int tl,int tr){


marked[v]=0;
if(tl==tr){
t[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=0;
}
}

void update(int v,int tl,int tr,int l,int r,int new_val){


if(marked[v]==true){
t[v*2]=t[v*2+1]=t[v];
marked[v*2]=marked[v*2+1]=true;
marked[v]=false;
}
if(l>r){
return;
}
if(l==tl&&tr==r){
t[v]=new_val;
marked[v]=true;
}else{
int tm=(tl+tr)/2;
update(v*2,tl,tm,l,min(r,tm),new_val);
update(v*2+1,tm+1,tr,max(l,tm+1),r,new_val);
}
}

int query(int v,int tl,int tr,int pos){


if(marked[v]==true){
t[v*2]=t[v*2+1]=t[v];
marked[v*2]=marked[v*2+1]=true;
marked[v]=false;
}
if(tl==tr){
return t[v];
}
int tm=(tl+tr)/2;
if(pos<=tm){
return query(v*2,tl,tm,pos);
}else{
return query(v*2+1,tm+1,tr,pos);
}
}

Range Assignment and Range Minimum Query

const int N=1e6+10;


int t[4*N];
int lazy[4*N];
int marked[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr) {
t[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=min(t[v*2],t[v*2+1]);
}
}

void update(int v,int tl,int tr,int l,int r,int new_val){


if(marked[v]==true){
t[v]=lazy[v];
if(tl!=tr){
lazy[v*2]=lazy[v];
lazy[v*2+1]=lazy[v];
marked[v*2]=marked[v*2+1]=true;
}
marked[v]=false;
}
if(l>r){
return;
}
if(l==tl&&tr==r){
t[v]=new_val;
lazy[v*2]=new_val;
lazy[v*2+1]=new_val;
marked[v*2]=marked[v*2+1]=true;
}else{
int tm=(tl+tr)/2;
update(v*2,tl,tm,l,min(r,tm),new_val);
update(v*2+1,tm+1,tr,max(l,tm+1),r,new_val);
t[v]=min(t[v*2],t[v*2+1]);
}
}

int query(int v,int tl,int tr,int l,int r){


if(marked[v]==true){
t[v]=lazy[v];
if(tl!=tr){
lazy[v*2]=lazy[v];
lazy[v*2+1]=lazy[v];
marked[v*2]=marked[v*2+1]=true;
}
marked[v]=false;
}
if(l>r){
return INT_MAX;
}
if(l==tl&&tr==r){
return t[v];
}
int tm=(tl+tr)/2;
return min(query(v*2,tl,tm,l,min(r,tm)),query(v*2+1,tm+1,tr,max(l,tm+1),r));
}

Range Assignment and Range Sum Query

const int N=1e6+7;


int seg[4*N];
int lazy[4*N];
bool marked[4*N];

void build(vector<int> &a,int v,int tl,int tr){


if(tl==tr){
seg[v]=a[tl];
}else{
int tm=(tl+tr)/2;
build(a,2*v,tl,tm);
build(a,v*2+1,tm+1,tr);
seg[v]=seg[2*v]+seg[2*v+1];
}
}

void update(int v,int tl,int tr,int l,int r,int new_val){


if(marked[v]==true){
seg[v]=(tr-tl+1)*lazy[v];
if(tl!=tr){
lazy[2*v]=lazy[2*v+1]=lazy[v];
marked[2*v]=marked[2*v+1]=true;
}
marked[v]=false;
}
if(r<tl || l>tr || tl>tr){
return;
}
if(tl>=l && tr<=r){
seg[v]=(tr-tl+1)*new_val;
if(tl!=tr){
lazy[2*v]=lazy[2*v+1]=new_val;
marked[2*v]=marked[2*v+1]=true;
}
return;
}
int tm=(tl+tr)/2;
update(v*2,tl,tm,l,r,new_val);
update(v*2+1,tm+1,tr,l,r,new_val);
seg[v]=seg[2*v]+seg[2*v+1];
}

int query(int v,int tl,int tr,int l,int r){


if(marked[v]==true){
seg[v]=(tr-tl+1)*lazy[v];
if(tl!=tr){
lazy[2*v]=lazy[2*v+1]=lazy[v];
marked[2*v]=marked[2*v+1]=true;
}
marked[v]=false;
}
if(r<tl || l>tr || tl>tr){
return 0;
}
if(tl>=l && tr<=r){
return seg[v];
}
int tm=(tl+tr)/2;
return query(2*v,tl,tm,l,r)+query(2*v+1,tm+1,tr,l,r);
}

Finding subsegments with the maximal sum

struct seg{
ll sum,pref,suff,ans;
};
const ll N=1e6+10;
seg t[4*N];

seg combine(seg l,seg r){


seg res;
res.sum=l.sum+r.sum;
res.pref=max(l.pref,l.sum+r.pref);
res.suff=max(r.suff,r.sum+l.suff);
res.ans=max(max(l.ans,r.ans),l.suff+r.pref);
return res;
}

seg make_seg(ll val){


seg res;
res.sum=val;
res.pref=res.suff=res.ans=max(0LL,val);
return res;
}

void build(vector<ll> &a,ll v,ll tl,ll tr){


if(tl==tr){
t[v]=make_seg(a[tl]);
}else{
ll tm=(tl+tr)/2;
build(a,v*2,tl,tm);
build(a,v*2+1,tm+1,tr);
t[v]=combine(t[v*2],t[v*2+1]);
}
}

void update(ll v,ll tl,ll tr,ll pos,ll new_val){


if(tl==tr){
t[v]=make_seg(new_val);
}else{
ll tm=(tl+tr)/2;
if(pos<=tm){
update(v*2,tl,tm,pos,new_val);
}else{
update(v*2+1,tm+1,tr,pos,new_val);
}
t[v]=combine(t[v*2],t[v*2+1]);
}
}

seg query(ll v,ll tl,ll tr,ll l,ll r){


if(l>r){
return make_seg(0);
}
if(l==tl&&r==tr){
return t[v];
}
ll tm=(tl+tr)/2;
return
combine(query(v*2,tl,tm,l,min(r,tm)),query(v*2+1,tm+1,tr,max(l,tm+1),r));
}

DSU

const int N=1e6+10;


int parent[N],sz[N];

void make_set(int v){


parent[v]=v;
sz[v]=1;
}
int find_set(int v){
if(v==parent[v]){
return v;
}
return parent[v]=find_set(parent[v]);
}

void union_sets(int a,int b){


a=find_set(a);
b=find_set(b);
if(a!=b){
if(sz[a]<sz[b]){
swap(a,b);
}
parent[b]=a;
sz[a]+=sz[b];
}
}

Xor of unique elements between segment

#include <bits/stdc++.h>
using namespace std;
#define IOS ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ll long long

struct Query{
int l,r,idx;
bool operator<(Query other)const{
return r<other.r;
}
};

const int N=1e6+10;


int t[4*N];

int query(int v,int tl,int tr,int l,int r){


if(l>r){
return 0;
}
if(l==tl&&r==tr){
return t[v];
}
int tm=(tl+tr)/2;
return (query(v*2,tl,tm,l,min(r,tm))^query(v*2+1,tm+1,tr,max(l,tm+1),r));
}

void update(int v,int tl,int tr,int pos,int new_val){


if(tl==tr){
t[v]=new_val;
}else{
int tm=(tl+tr)/2;
if(pos<=tm){
update(v*2,tl,tm,pos,new_val);
}else{
update(v*2+1,tm+1,tr,pos,new_val);
}
t[v]=(t[v*2]^t[v*2+1]);
}
}

int main(){
IOS
int n;
cin>>n;
vector<int> a(n+1);
for(int i=1;i<=n;++i){
cin>>a[i];
}
int q;
cin>>q;
vector<Query> Q(q+1);
for(int i=1;i<=q;++i){
int l,r;
cin>>l>>r;
Q[i].l=l;
Q[i].r=r;
Q[i].idx=i;
}
sort(Q.begin(),Q.end());
map<int,int> last;
vector<int> res(q+1);
int j=0;
for(int i=1;i<=q;++i){
while(j<Q[i].r){
j++;
update(1,0,n,j,a[j]);
update(1,0,n,last[a[j]],0);
last[a[j]]=j;
}
res[Q[i].idx]=query(1,0,n,Q[i].l,Q[i].r);
}
for(int i=1;i<=q;++i){
cout<<res[i]<<"\n";
}
return 0;
}

You might also like