模板
模板
读写读入
快读
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;
}

浙公网安备 33010602011771号