C++ 刷题模板
自己用的一套模板,持续更新中,里面都是自己用到过的一些数据结构
新增珂朵莉树
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<string>
#include<stack>
#include<algorithm>
#include<bitset>
#include<queue>
#include<iomanip>
#include<ctime>
#include<cstring>
#include<random>
#include <numeric> //求和函数 accumulate(v.begin(),v.end(),0);
using namespace std;
typedef pair<int,pair<int,int>> pii;
typedef pair<int,int> pi;
typedef pair<long long,pair<int,int>> pll;
typedef long long ll;
typedef unsigned long long ull;
mt19937 gen{random_device{}()};
uniform_real_distribution<double> dis;
//优先队列定义参考
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q; //升序
//链表节点
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
//二叉树节点
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
//有父节点的二叉树节点
struct TreeNodes {
int val;
TreeNodes *left;
TreeNodes *right;
TreeNodes *parent;
int crp=0;
TreeNodes() : val(0), left(nullptr), right(nullptr) ,parent(nullptr){}
TreeNodes(int x) : val(x), left(nullptr), right(nullptr),parent(nullptr),crp(0){}
TreeNodes(int x, TreeNodes *left, TreeNodes *right, TreeNodes *parent) : val(x), left(left), right(right),parent(parent) {}
};
//图结点
class Node {
public:
int val;
vector<Node*> neighbors;
Node() {
val = 0;
neighbors = vector<Node*>();
}
Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}
Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
//字典树
class Trie{
public:
Trie* next[26]={nullptr};
bool isEnd;
Trie(){isEnd=false;}
void insert(string s){
Trie* curPos=this;
for(int i=s.length()-1;i>=0;i--){
int t=s[i]-'a';
if(curPos->next[t]==nullptr){
curPos->next[t]=new Trie;
}
curPos=curPos->next[t];
}
curPos->isEnd=true;
}
};
// class Trie{
// public:
// Trie* next[26]={nullptr};
// bool isEnd=false;
// Trie(){isEnd=false;}
// void insert(string s){
// Trie* cur=this;
// for(int i=0;i<s.length();i++){
// int c=s[i]-'a';
// if(cur->next[c]==nullptr){
// cur->next[c]=new Trie();
// }
// cur=cur->next[c];
// }
// cur->isEnd=true;
// }
// };
//有秩和无秩两种并查集
class UnionFind{
public:
vector<int>pa;
vector<int>ranks;
int count;
UnionFind(int n){
count=n;
pa.resize(n);
ranks.resize(n,1);
for(int i=0;i<n;i++) pa[i]=i;
}
int find(int x){
if(pa[x]==x) return x;
return find(pa[x]);
}
void merge(int x,int y){
x=find(x);
y=find(y);
if(x==y) return;
if(ranks[x]<=ranks[y]){
pa[x]=y;
if(ranks[x]==ranks[y]) ranks[y]++;
}else pa[y]=x;
}
// int find(int x){
// if(pa[x]==x) return x;
// return pa[x]=find(pa[x]);
// }
// void merge(int x,int y){
// x=find(x);
// y=find(y);
// if(x==y) return;
// pa[x]=y;
// }
};
//静态线段树
class SegmentTree {
public:
struct Node {
int val,l,r;
Node *left;
Node *right;
Node(int x,int l,int r) : val(x),l(l),r(r),left(nullptr), right(nullptr) {}
};
Node *root;
SegmentTree(vector<int>& nums){ root=build(nums,0,nums.size()-1); }
Node* build(vector<int>& nums,int l,int r){
Node* node;
if(l==r){
node=new Node(nums[l],l,r);
return node;
}
int m=(l+r)/2;
Node* n1=build(nums,l,m);
Node* n2=build(nums,m+1,r);
node=new Node(n1->val+n2->val,l,r);
node->left=n1;
node->right=n2;
return node;
}
void updateNode(int index,int val,Node* node){
if(node->l==node->r){ node->val=val; return; }
int m=(node->l+node->r)/2;
if(index<=m) updateNode(index,val,node->left);
else updateNode(index,val,node->right);
node->val=node->left->val+node->right->val;
}
int sumNode(int left, int right,Node* node){
if(node->l>=left&&node->r<=right) return node->val;
int m=(node->l+node->r)/2;
if(right<=m) return sumNode(left,right,node->left);
if(left>m) return sumNode(left,right,node->right);
return sumNode(left,right,node->left)+sumNode(left,right,node->right);
}
};
//动态线段树
typedef long long ll;
class SegmentTreeDynSingal {
public:
struct Node {
//默认l,r为正数,如果不是正数自己想办法,不会加个常数啊
ll val,l,r;
Node *left;
Node *right;
Node(ll x,ll l,ll r) : val(x),l(l),r(r),left(nullptr), right(nullptr) {}
};
Node *root;
SegmentTreeDynSingal(ll m){ root=new Node(0,0,m); }
//不管嘛,只能单点修改,而且是变化值,不是修改后的值
void updateNode(Node* node,ll index,ll val){
if(node->l==node->r){ node->val+=val; return; }
ll m=(node->l+node->r)/2;
if(index<=m) {
if(node->left==nullptr) node->left=new Node(0,node->l,m);
updateNode(node->left,index,val);
}else {
if(node->right==nullptr) node->right=new Node(0,m+1,node->r);
updateNode(node->right,index,val);
}
ll left=0,right=0;
if(node->left!=nullptr) left=node->left->val;
if(node->right!=nullptr) right=node->right->val;
node->val=left+right;
}
int queryNode(Node* node, ll left, ll right){
if(node==nullptr||right<node->l||left>node->r) return 0;
if(node->l>=left&&node->r<=right) return node->val;
ll m=(node->l+node->r)/2;
return queryNode(node->left,left,right)+queryNode(node->right,left,right);
}
};
//动态加点范围更新求最大
class SegmentTreeDynArr {
struct Node { //默认l,r为正数,如果不是正数自己想办法,不会加个常数啊
int val,max,l,r;
Node *left;
Node *right;
Node(int x,int l,int r) : val(x),l(l),r(r),max(x),left(nullptr), right(nullptr) {}
};
Node *root;
void build(int m){ root=new Node(0,0,m); }
void update(Node* node,int l,int r,int val){//要支持只能区间修改,是变化值,不是修改后的值
if(l>node->r||r<node->l) return;
if(node->l>=l&&node->r<=r){
node->val=max(node->val,val);
node->max=max(node->max,val);
return;
}
push_down(node);
update(node->left,l,r,val);
update(node->right,l,r,val);
node->val=min(node->left->val,node->right->val);
node->max=max(node->left->max,node->right->max);
}
void push_down(Node* node){
int m=(node->l+node->r)/2;
if(node->left==nullptr) node->left=new Node(node->val,node->l,m);
if(node->right==nullptr) node->right=new Node(node->val,m+1,node->r);
node->left->val=max(node->val,node->left->val);
node->right->val=max(node->val,node->right->val);
node->left->max=max(node->val,node->left->max);
node->right->max=max(node->val,node->right->max);
}
int query(Node* node, int left, int right){
if(node==nullptr||right<node->l||left>node->r) return 0;
if(node->l>=left&&node->r<=right) return node->max;
push_down(node);
return max(query(node->left,left,right),query(node->right,left,right));
}
};
//字符串分割
vector<string>split(string &s,char c){
int i=0;
vector<string>v;
while (i<s.length()) {
while (i<s.length()&&s[i]==c) i++;
int j=i;
while (j<s.length()&&s[j]!=c) j++;
if(i!=j) v.push_back(s.substr(i,j-i));
i=j;
}
return v;
}
//线段树数组版
class SegmentTreeDyn {
public:
vector<int>arr;
int n=1;//n一定是2的整数倍
void build(int x){//数据范围,0到x
while(n<=x) n*=2;
arr.resize(2*n+1,0);
}
void add(int p,int x){//p只能从0开始
int s=p+n;
while(s>0){
arr[s]+=x;
s=s>>1;
}
}
int query(int left,int right,int l,int r,int s){
if(left>r||right<l) return 0;
if(left<=l&&right>=r) return arr[s];
int mid=(l+r)/2;
int res=0;
res+=query(left,right,l,mid,s*2);
res+=query(left,right,mid+1,r,s*2+1);
return res;
}
int query(int left,int right){
return query(left,right,0,n-1,1);
}
};
//珂朵莉树
class ChthollyTree{
struct node {
int l,r;
mutable int v;
node(int l,int r,int v):l(l),r(r),v(v) {}
bool operator<(const node &o) const {return l<o.l;}
};
set<node>tree;
auto split(int pos){
if(pos > tree.rbegin()->r) return tree.end();
auto it=tree.lower_bound(node(pos,0,0));
if(it!=tree.end()&&it->l==pos) return it;
it--;
int l=it->l,r=it->r,v=it->v;
tree.erase(it);
tree.insert(node(l,pos-1,v));
return tree.insert(node(pos,r,v)).first;
}
void assign(int l,int r, int v){
auto end=split(r+1),begin=split(l);
tree.erase(begin,end);
tree.insert(node(l,r,v));
}
};
//树状数组
#define MAXN 80005
#define lowbit(x) ((x) & (-x))
long long tree[MAXN]={};
void update(int i, int x){
for (int pos = i; pos < MAXN; pos += lowbit(pos)) tree[pos] += x;
}
int query(int n){
int ans = 0;
for (int pos = n; pos; pos -= lowbit(pos)) ans += tree[pos];
return ans;
}
int query(int a, int b){ return query(b) - query(a - 1); }
/**
* 除法求模:
* 求(a/b) %p,若已知b%p的逆元是c=> b*c%p = 1,
* (a/b) %p = ((a*c%p)/(b*c%p))%p = (a*c%p)%p = (a%p)(c%p)%p
*
* 逆元:
* a对p(质数)的逆元,a^(p-2)
*
* 组合数学:
* C(n,m)=n!/m!(n-m)!
*/
const ll mod=1000000007;
ll fact[2000003]={};
void factorial(int n){
fact[0]=1;
for(int i=1;i<n;i++){
fact[i]=(i*fact[i-1])%mod;
}
}
ll power(ll a, ll b) {
ll ans=1;
a%=mod;
while (b) {
if(b&1) { ans*=a; ans%=mod; }
b>>=1; a*=a; a%=mod;
}
return ans;
}
ll nCr(int n,int m){
ll pm=power(fact[m],mod-2);
ll pnm=power(fact[n-m],mod-2);
return ((fact[n]*pm)%mod*pnm)%mod;
}
struct pair_hash{
size_t operator()(const pair<int,int>& a)const {
return hash<long long>()(a.first)*2333+hash<long long>()(a.second);
}
};
ll gcd(ll a,ll b) {return a%b==0?b:gcd(b,a%b);}
//扩展欧几里得
/*
题目里很少有要求 ax+by=gcd(a,b) 的整数解,一般都是求 ax+by=c 的整数解。
这时该怎么办呢?
如果 gcd(a,b)|c,那么我们在等式两边同乘以 c/gcd(a,b) 即可得到整数解。
否则函数无整数解
*/
pi exgcd (int a, int b) {
if (b == 0) return pi(1,0);
auto [x,y]=exgcd (b, a%b);
int t = x;
x = y;
y = t - a / b * y;
return pi(x,y);
}
int exgcd (int a, int b,int &x,int &y,int &d) {
if (b == 0) {
d=a;
return d;
}
d=exgcd(b, a%b,x,y,d);
int t = x;
x = y;
y = t - a / b * y;
return d;
}
//求逆元
int inv(int a, int mod) {
int x, y, d;
exgcd(a, mod, x, y, d);
if (d != 1) {
// a 和 mod 不互质,没有乘法逆元
return -1;
}
return (x % mod + mod) % mod;
}
// 计算 R
//int r = (p * inv(q, MOD)) % MOD;
int rand_ab(int a,int b){ //[a,b)
return (rand() % (b-a))+ a;
}
double rand_01(){ //[0,1]
return rand() / double(RAND_MAX);
}
int _IO=[](){
ios::sync_with_stdio(0);
cin.tie(0); //cout.tie(0);
return 0;
}();
int main(){
system("pause");
}
力扣刷题题单
面试: 121 122 123 217 218 220 1 15 18 2 344 541 387 1143 1721 92 19 5
88 347 215 162 287 34 155 20 200 752 494 94
base:
1) 贪心:330 334 621
2)单调栈:85 316 321 406 456 496 503 739 768 769 975
3)图:133 207 210 310 329 332 399 753
4)堆:23 215 218 239 264 347 373 378 407
5)并查集:128 130 200 684 685 765
6)前缀和:209 238 363 497 560 523 525
7)有序集合:218 220 315 327 699 715
9)树状数组:307 315 327 493 673
8)字典树: 139 140 212 386
13) 数组:907
12) dp:279 322 416 474 494 518 552 879 1049 1449
plus:
字符串:30
数组:1856 2104
最小生成树:1489 1584
滚动哈希:214 718 1044 1147 1316 1392 1923
扫描线:391 1851
拓扑排序:913 1728 1203 1591
强连通分量:1568
双连通分量:1192 LCP54
拒绝采样:470 478
状态压缩:464 526 638 691 805 847 943 996
交互:374 843 1095 1237
最短路:743 787 882 1368
组合数学:62 458 920 1359 1467