Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 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