すきだよ

导航

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

练习题

posted on 2022-09-07 09:31  すきだよ  阅读(54)  评论(0编辑  收藏  举报