模板

模板

读写读入

快读

int read()
{
    int s = 0,f = 1; char x = getchar();
    while(x < '0' || '9' < x) f = (x == '-') ? -1 : 1 , x = getchar();
    while('0' <= x && x <= '9') s = s * 10 + x - '0' , x = getchar();
    return s * f;
}

关闭绑定锁

ios::sync_with_stdio(false);

读入字符串

读入字符串至空格为止

const int N = 1010;

char c[N];
scanf("%s",c);

或者

string c;
scanf("%s",c);

读入一行字符串

const int N = 1010;
char s[N];
cin.getline(s,N);

或者

string s;
getline(cin,s);

重载运算符

想让a < b的条件变为a.fi < b.fi

struct node
{
    int fi,se;
    friend node operator < (node a,node b)//a < b
    {
        return a.fi < b.fi;
    }
};

或者矩阵乘法重载 * 运算

const int N = 1010;

struct mat
{
    int m[N][N];
    mat()
    {
        memset(m,0,sizeof 0);
    }
    friend mat operator * (mat A,mat B)
    {
        mat C;
        for (int i = 1;i <= n;i ++)
        {
            for (int j = 1;j <= n;j ++)
            {
                for (int k = 1;k <= n;k ++)
                {
                    C.m[i][j] = C.m[i][j] + A.m[i][k] * B.m[k][j];
                }
            }
        }
        return C;
    }
};

数据结构

单调队列

单调递增队列,滑动窗口长度不超过k

const int N = 1010;

int q[N],a[N];

for (int i = 1,h = 1,t = 0;i <= n;i ++)
{
    while(h <= t && i - q[h] >= k) h ++;
    while(h <= t && a[i] <= a[q[t]]) t --;//保证单调递增
    q[++ t] = i;
}

线段树

区间加区间乘区间查询

const int N = 1e5 + 10;

struct tree
{
    int l,r;
    int len,sum;
    int lz1,lz2;
}tr[N << 2];

void build(int p,int l,int r)
{
    tr[p].l = l , tr[p].r = r;
    tr[p].len = r - l + 1;
    tr[p].lz1 = 1;
    tr[p].lz2 = 0;
    if (l == r)
    {
        tr[p].sum = a[l];
        return;
    }
    build(lp,l,mid);
    build(rp,mid + 1,r);
    tr[p].sum = (tr[lp].sum + tr[rp].sum) % mo;
    return;
}

void push_down(int p)
{
    tr[lp].lz2 = (tr[lp].lz2 * tr[p].lz1) % mo;
    tr[lp].lz2 = (tr[lp].lz2 + tr[p].lz2) % mo;
    tr[lp].lz1 = (tr[lp].lz1 * tr[p].lz1) % mo;
    tr[lp].sum = (tr[lp].sum * tr[p].lz1) % mo;
    tr[lp].sum = (tr[lp].sum + tr[p].lz2 * tr[lp].len) % mo;

    tr[rp].lz2 = (tr[rp].lz2 * tr[p].lz1) % mo;
    tr[rp].lz2 = (tr[rp].lz2 + tr[p].lz2) % mo;
    tr[rp].lz1 = (tr[rp].lz1 * tr[p].lz1) % mo;
    tr[rp].sum = (tr[rp].sum * tr[p].lz1) % mo;
    tr[rp].sum = (tr[rp].sum + tr[p].lz2 * tr[rp].len) % mo;

    tr[p].lz1 = 1 , tr[p].lz2 = 0;
    return;
}

void add1(int p,int L,int R,int x)//区间乘
{
    int l = tr[p].l,r = tr[p].r;
    if (L <= l && r <= R)
    {
        tr[p].sum = (tr[p].sum * x) % mo;
        tr[p].lz1 = (tr[p].lz1 * x) % mo;
        tr[p].lz2 = (tr[p].lz2 * x) % mo;
        return;
    }
    if (r < L || R < l) return;
    push_down(p);
    add1(lp,L,R,x);
    add1(rp,L,R,x);
    tr[p].sum = (tr[lp].sum + tr[rp].sum) % mo;
    return;
}

void add2(int p,int L,int R,int x)//区间加
{
    int l = tr[p].l,r = tr[p].r;
    if (L <= l && r <= R)
    {
        tr[p].sum = (tr[p].sum + x * tr[p].len) % mo;
        tr[p].lz2 = (tr[p].lz2 + x) % mo;
        return;
    }
    if (r < L || R < l) return;
    push_down(p);
    add2(lp,L,R,x);
    add2(rp,L,R,x);
    tr[p].sum = (tr[lp].sum + tr[rp].sum) % mo;
    return;
}

int query(int p,int L,int R)//区间查询
{
    int l = tr[p].l,r = tr[p].r;
    if (L <= l && r <= R) return tr[p].sum;
    if (r < L || R < l) return 0;
    push_down(p);
    return (query(lp,L,R) + query(rp,L,R)) % mo;
}

树状数组

区间修改单点查询

int lowbit(int x)
{
    return x & -x;
}

void add(int id,int x)
{
    while(id <= n) tr[id] += x , id += lowbit(id);
    return;
}

int sum(int id)
{
    int res = 0;
    while(id) res += tr[id] , id -= lowbit(id);
    return res;
}

树上操作

树剖

重链剖分求最近公共祖先

int s[N],son[N];//s子节点数,son重儿子编号
int d[N],f[N],tp[N];//d到根节点距离,f父亲节点,tp链顶

vector <int> e[N];

void dfs1(int x,int fa)
{
    f[x] = fa;
    d[x] = d[fa] + 1;
    s[x] = 1;
    for (int i = 0,v;i < e[x].size();i ++)
    {
        v = e[x][i];
        if (v == fa) continue;
        dfs1(v,x);
        s[x] += s[v];
        if (s[v] > s[son[x]]) son[x] = v;//重儿子为子节点数最多的节点
    }
    return;
}

void dfs2(int x,int top)
{
    tp[x] = top;
    if (!son[x]) return;
    dfs2(son[x],top);//重儿子连成一条链
    for (int i = 0,v;i < e[x].size();i ++)
    {
        v = e[x][i];
        if (v == f[x] || v == son[x]) continue;
        dfs2(v,v);//新的链
    }
    return;
}

int lca(int x,int y)
{
    while(tp[x] != tp[y])
    {
        if (d[f[tp[x]]] < d[f[tp[y]]]) swap(x,y);
        x = f[tp[x]];
    }
    if (d[x] > d[y]) swap(x,y);
    return x;
}

图论

强联通分量

有向图缩点

void tarjan(int x)
{
    dfn[x] = low[x] = ++ tim;
    stk[++ top] = x;
    for (int i = 0,v;i < e[x].size();i ++)
    {
        v = e[x][i];
        if (!dfn[v]) tarjan(v) , low[x] = min(low[x],low[v]);
        else if (!sd[v]) low[x] = min(low[x],dfn[v]);
    }
    if (dfn[x] == low[x])
    {
        int v;
        ++ ct;
        while(1)
        {
            v = stk[top --];
            sd[v] = ct;
            sum[ct] += a[v];
            if (v == x) break;
        }
    }
    return;
}
posted @ 2023-10-19 19:26  9981day  阅读(38)  评论(0)    收藏  举报