vector<int>arr;vector<int>tree;arr.resize(N+1);tree.resize(4*N);voidbuild(intp,intl,intr){if(l==r){tree[p]=arr[l];return;}intmid=(l+r)/2;build(2*p,l,mid);build(2*p+1,mid+1,r);tree[p]=min(tree[2*p],tree[2*p+1]);}voidupdate(intp,intl,intr,intx,inty){// turn arr[x] into yif(l==r){tree[p]=y;return;}intmid=(l+r)/2;if(x<=mid){update(2*p,l,mid,x,y);}else{update(2*p+1,mid+1,r,x,y);}tree[p]=min(tree[2*p],tree[2*p+1]);}intquery(intp,intl,intr,intx,inty){if(l==r){returntree[p];}intmid=(l+r)/2;intans=INT_MAX;if(x<=mid){ans=min(ans,query(2*p,l,mid,x,y));}if(y>=mid+1){ans=min(ans,query(2*p+1,mid+1,r,x,y));}returnans;}
template<classT>structSeg{// comb(ID,b) = bconstTID=1e18;Tcomb(Ta,Tb){returnmin(a,b);}intn;vector<T>seg;voidinit(int_n){n=_n;seg.assign(2*n,ID);}voidpull(intp){seg[p]=comb(seg[2*p],seg[2*p+1]);}voidupd(intp,Tval){// set val at position pseg[p+=n]=val;for(p/=2;p;p/=2)pull(p);}Tquery(intl,intr){// min on interval [l, r]Tra=ID,rb=ID;for(l+=n,r+=n+1;l<r;l/=2,r/=2){if(l&1)ra=comb(ra,seg[l++]);if(r&1)rb=comb(seg[--r],rb);}returncomb(ra,rb);}};Seg<int>st;st.upd(i,x);inta=st.query(x,y);
intT=1;vector<int>st,ed,depth;vector<vector<int>>up(2e5+1,vector<int>(20));//tourtoflatternthetreevoiddfs(intn,intp){st[n]=T;depth[n]=depth[p]+1;//jump table for node nup[n][0]=p;for(inti=1;i<20;i++){up[n][i]=up[up[n][i-1]][i-1];}T++;for(autoc:adj[n]){if(c!=p){dfs(c,n);}}ed[n]=T-1;}intlca(inta,intb){if(depth[a]<depth[b])swap(a,b);intdiff=depth[a]-depth[b];for(inti=0;i<20;i++){if((diff>>i)&1){a=up[a][i];}}if(a==b)returna;for(inti=19;i>=0;i--){intap=up[a][i];intbp=up[b][i];if(ap!=bp){a=ap;b=bp;}}returnup[a][0];}//dfs to get depth and initialize jump tabledepth[0]=-1;dfs(1,0);//lcaintl=lca(a,b);
//dfs1 to get depth, parent and sz of each nodevoiddfs(intn,intp){// make treesdepth[n]=depth[p]+1;sz[n]=1;for(autoi:adj[n]){if(i!=p){parent[i]=n;dfs(i,n);sz[n]+=sz[i];}}}intT=1;//dfs2 to flatten and get index T of node, head of nodevoiddfs2(intn,inth,intp){st[n]=T++;//do some calculation.e.g seg.upd(st[n], values[n]);head[n]=h;inthv=-1;for(autoi:adj[n]){if(i!=p){if(hv==-1||sz[i]>sz[hv]){hv=i;}}}// leaf node, then returnif(hv==-1)return;// heavy edge = inheritdfs2(hv,h,n);// other eddge, start a new segmentfor(autoi:adj[n]){if(i!=p&&i!=hv){// light edge = new segmentdfs2(i,i,n);}}}//do something for 2 nodes ...inthldquery(inta,intb){intans=0;while(head[a]!=head[b]){if(depth[head[a]]<depth[head[b]])swap(a,b);intq1=seg.query(st[head[a]],st[a]);a=parent[head[a]];ans=max(ans,q1);}if(depth[a]<depth[b])swap(a,b);intq2=seg.query(st[b],st[a]);ans=max(ans,q2);returnans;}
priority_queue<int>q;//biggest on toppriority_queue<int,vector<int>,less<int>>q;//biggest on toppriority_queue<int,vectot<int>,greater<int>>q;//smallest on topstructcmp{booloperator()(pair<int,int>&a,pair<int,int>&b){if(a.first!=b.first)returna.first<b.first;elsereturna.second<b.second;}};priority_queue<rec,vector<rec>,cmp>q;
// C = A + B, A >= 0, B >= 0vector<int>add(vector<int>&A,vector<int>&B){if(A.size()<B.size())returnadd(B,A);vector<int>C;intt=0;for(inti=0;i<A.size();i++){t+=A[i];if(i<B.size())t+=B[i];C.push_back(t%10);t/=10;}if(t)C.push_back(t);returnC;}// C = A - B, A >= B, A >= 0, B >= 0vector<int>sub(vector<int>&A,vector<int>&B){vector<int>C;for(inti=0,t=0;i<A.size();i++){t=A[i]-t;if(i<B.size())t-=B[i];C.push_back((t+10)%10);if(t<0)t=1;elset=0;}while(C.size()>1&&C.back()==0)C.pop_back();returnC;}// C = A * b, A >= 0, b > 0vector<int>mul1(vector<int>&A,intb){vector<int>C;intt=0;for(inti=0;i<A.size()||t;i++){if(i<A.size())t+=A[i]*b;C.push_back(t%10);t/=10;}while(C.size()>1&&C.back()==0)C.pop_back();returnC;}// C = A * Bvector<int>mul2(vector<int>&A,vector<int>&B){vector<int>C(A.size()+B.size(),0);for(inti=0;i<A.size();i++)for(intj=0;j<B.size();j++)C[i+j]+=A[i]*B[j];intt=0;for(inti=0;i<C.size();i++){t+=C[i];C[i]=t%10;t/=10;}while(C.size()>1&&C.back()==0)C.pop_back();returnC;}// A / b = C ... r, A >= 0, b > 0vector<int>div(vector<int>&A,intb,int&r){vector<int>C;r=0;for(inti=A.size()-1;i>=0;i--){r=r*10+A[i];C.push_back(r/b);r%=b;}reverse(C.begin(),C.end());while(C.size()>1&&C.back()==0)C.pop_back();returnC;}
Prefix Sum
1D Prefix Sum
1
2
3
4
5
6
for(inti=1;i<=N;i++){pre[i]=val[i]+pre[i-1];}//sum from a to b inclusivepre[b]-pre[a-1]
for(inti=1;i<=N;i++){for(intj=1;j<=N;j++){pre[i][j]=val[i][j]+pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];}}//sum of the range from (x1, y1) to (x2, y2) is:pre[x2][y2]-pre[x1-1][y2]-pre[x2][y1-1]+pre[x1-1][y1-1]
Reverse 2D Prefix Sum
1
2
3
4
5
6
7
8
9
10
11
12
// add v to the range from (x1, y1) to (x2, y2), inclusiveval[x1][y1]+=v;val[x1][y2+1]-=v;val[x2+1][y1]-=v;val[x2+1][y2+1]+=v;// get value at (i,j)for(inti=1;i<=N;i++){for(intj=1;j<=N;j++){val[i][j]+=+pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];}}
Bit Operation
The k-th bit of an integer n
1
n>>k&1
The first LSB 1 and it’s trailing 0s
1
lowbit(n)=n&-n
2 Pointers
1
2
3
4
5
6
for(inti=0,j=0;i<n;i++){while(j<i&&check(i,j))j++;// your code}
Coordinate Compression
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
vector<int>alls;// store all input valuessort(alls.begin(),alls.end());alls.erase(unique(alls.begin(),alls.end()),alls.end());// remove duplicates// use binary search to find coordinate of value x// can also be done using upper_bound(alls.begin(), all.end(), x)intfind(intx){returnupper_bound(alls.begin(),alls.end(),x)-alls.begin();}//add is array of pairs, first is the uncompressed index, second is the operation to add//a is the compressed array, each index is compressed from original indexmap<int,int>a;for(autoitem:add){intcompressed_index=find(item.first);a[compressed_index]+=item.second;}
// combine the over lapping rangesvoidmerge(vector<pair<int,int>>&segs){vector<pair<int,int>>res;sort(segs.begin(),segs.end());intst=-2e9,ed=-2e9;//[st, ed]: the last rangefor(autoseg:segs)//case 1: can't merge new rangeif(ed<seg.first){if(st!=-2e9)res.push_back({st,ed});st=seg.first,ed=seg.second;}else//case 2: the new range's end is smaller than last range's end//case 3: the new range's end is bigger than last range's end//in both cases, extend the new end for the last rangeed=max(ed,seg.second);if(st!=-2e9)res.push_back({st,ed});segs=res;}
Monotonous Stack
1
2
3
4
5
6
7
8
9
10
11
12
//Open a stack and decrease monotonically.//For the top element on the stack, what you can see is the number of elements behindstack<int>s;for(inti=0;i<n;i++){inttemp;cin>>temp;//When the input is bigger, remove the smaller from the stackwhile(!s.empty()&&temp>=s.top())s.pop();s.push(temp);}
Sliding Window
Use monotonous queue to find minimal in a sliding window.
deque<int>dq;//find the minimal number in the sliding windowfor(inti=0;i<n;i++){//keep the front of the deque always inside sliding window of size kif(!dq.empty()&&k<i-dq.front()+1)dq.pop_front();//maintain monotonous queue//if the queue is not empty and the tail element is not smaller than a[i]//pop all the bigger elements until it is smaller than a[i]while(!dq.empty()&&a[dq.back()]>=a[i])dq.pop_back();dq.push_back(i);if(i+1>=k)cout<<a[dq.front()]<<" ";}
//ne: based on pattern string p//ne[i] = j, j the maximal length of prefix: ne[1:j] == ne[i-j+1:i]for(inti=2,j=0;i<=m;i++){while(j&&p[i]!=p[j+1])j=ne[j];if(p[i]==p[j+1])j++;ne[i]=j;}for(inti=1,j=0;i<=n;i++){while(j&&s[i]!=p[j+1])j=ne[j];if(s[i]==p[j+1])j++;if(j==m){j=ne[j];}}
intson[N][26],cnt[N],idx;// 0 is the root, and empty node // son[p][u] stores p's subtree root node// cnt[p] stores number of words ending with p nodevoidinsert(stringstr){intp=0;for(inti=0;i<str.size();i++){intu=str[i]-'a';if(!son[p][u])son[p][u]=++idx;p=son[p][u];}cnt[p]++;}intquery(stringstr){intp=0;for(inti=0;str.size();i++){intu=str[i]-'a';if(!son[p][u])return0;p=son[p][u];}returncnt[p];}