My Templates
ThisIsAName
2020-11-05 22:03:48
# My Templates
>蒟蒻11.5到11.6写的模板在这里了QAQ。
>
>就是分享模板吧,当然如果有dalao可以找到我的bug也是不错的。
>
>提及的题号是用于检测模板的题目。
>
------
## 程序构架
### 一般模板
注意是否需要读入负数
快读(不带负)
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
return 0;
}
```
快读(带负)
> P1001 A+B Problem
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
bool f=false;
while((c=getchar())<'0' || c>'9') if(c=='-') f=true;
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
if(f) x=-x;
}
template <typename T> void Wri(T x)
{
if(x > 9) Wri(x/10);
putchar(x%10^48);
}
template <typename T> void Oput(T x)
{
if(x < 0) putchar('-'), x=-x;
Wri(x);
}//快写一定要和快读判负一起修改
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
return 0;
}
```
## 基础算法
### 二分
二分查找
> P2249 【深基13.例1】查找
这种写法`l`刚好落在交界线右侧,`r`落在左侧。
```cpp
il int Binary(int x)
{
int l=1, r=n;
while(l <= r)
{
int mid = (l+r)>>1;
if(a[mid]<x) l=mid+1; //实现lower_bound
else r=mid-1;
}
return l;
}
```
二分答案
> P1182 数列分段 Section II
其实是另一种写法
```cpp
il LL Binary(LL l, LL r)
{
while(l != r)
{
LL mid = (l&r)+((l^r)>>1);
if(check(mid)) r=mid;
else l=mid+1;
}
return l;
}
```
### 排序
快排
> P1177 【模板】快速排序
```cpp
void qsort(int l, int r)
{
int i=l, j=r, mid=a[rand()%(r-l+1)+l];
do
{
while(a[i]<mid) ++i;
while(a[j]>mid) --j;
if(i<=j)
{
swap(a[i], a[j]);
++i, --j;
}
}while(i<=j);
if(i<r) qsort(i, r);
if(j>l) qsort(l, j);
}
```
第k大数:
> P1923 【深基9.例4】求第 k 小的数
```cpp
void kth_element(int l, int r, int k)
{
int i=l, j=r, mid=a[(l+r>>1)];
do
{
while(a[i]<mid) ++i;
while(a[j]>mid) --j;
if(i<=j)
{
swap(a[i], a[j]);
++i, --j;
}
}while(i<=j);
if(k<=j) kth_element(l, j, k);
else if(k>=i) kth_element(i, r, k);
}
```
归并
> P1177 【模板】快速排序
```cpp
int t[MAXN];
void msort(int l, int r)
{
if(l == r) return ;
int mid=(l+r)>>1, i=l, j=mid+1, k=l;
msort(l, mid);
msort(mid+1, r);
while(i<=mid && j<=r)
{
if(a[i]<a[j]) t[k++] = a[i++];
else t[k++] = a[j++];
}
while(i<=mid) t[k++] = a[i++];
while(j<=r) t[k++] = a[j++];
for(rg int m=l ; m<=r ; ++m)
a[m] = t[m];
}
```
归并求逆序对:
> P1908 逆序对
```cpp
LL ans; //注意long long
int t[MAXN];
void msort(int l, int r)
{
if(l == r) return;
int mid=(l+r)>>1, i=l, j=mid+1, k=l;
msort(l, mid);
msort(mid+1, r);
while(i<=mid && j<=r)
{
if(a[i]<=a[j]) t[k++] = a[i++];
else t[k++] = a[j++], ans += mid-i+1;
}
while(i<=mid) t[k++] = a[i++];
while(j<=r) t[k++] = a[j++];
for(rg int m=l ; m<=r ; ++m)
a[m] = t[m];
}
```
### 倍增
ST表
> P3865 【模板】ST表
```cpp
#define MAXN 100010
#define LOGN 17
int n, m;
int a[MAXN];
int Log[MAXN];
int st[MAXN][LOGN+1]; //数组开够
il void get_Log()
{
Log[0] = -1;
for(rg int i=1 ; i<=n ; ++i)
Log[i] = Log[i>>1] + 1;
}
il void prepare()
{
for(rg int i=1 ; i<=n ; ++i)
st[i][0] = a[i];
for(rg int i=1 ; i<=Log[n] ; ++i)
for(rg int j=1 ; j<=n&&(j+(1<<i-1))<=n ; ++j)//注意这个条件:会RE
st[j][i] = max(st[j][i-1], st[j+(1<<i-1)][i-1]);
}
il int query(int l, int r)
{
int t = Log[r-l+1];
return max(st[l][t], st[r-(1<<t)+1][t]);
}
int main()
{
Iput(n), Iput(m);
get_Log(); //线段树建树同理
for(rg int i=1 ; i<=n ; ++i)
Iput(a[i]);
prepare(); //线段树建树同理
for(rg int i=1 ; i<=m ; ++i)
{
int l, r;
Iput(l), Iput(r);
Oput(query(l, r));
putchar('\n');
}
return 0;
}
```
### 高精度
## 数据结构
### 链表
> P1996 约瑟夫问题
删除操作
```cpp
r[l[p]] = r[p];
l[r[p]] = l[p];
```
### 栈
### 队列
循环队列
```cpp
#define MAXQ (1<<...)
int q[MAXQ], l=1, r;
q[++r & MAXQ-1] = ...
q[l++ & MAXQ-1] = ...
q[--l & MAXQ-1] = ...
```
单调队列
```cpp
for(rg int i=1 ; i<=n ; ++i) //注意n的取值
{
if(l<=r && q[l]<i-m) ++l; //注意m的取值
...
while(l<=r && cmp(f(q[r]), f(i))) --r;
q[++r] = i;
}
```
优先队列(其实是堆 //STL香
```cpp
priority_queue <Type> q; //默认大根堆
```
### 堆
STL见上
对顶堆
> P1168 中位数
```cpp
priority_queue <int> bigq, smlq;
int main()
{
int n;
Iput(n);
for(rg int i=1 ; i<=n ; i++)
{
int t;
Iput(t);
if(i&1)
{
smlq.push(-t);
bigq.push(-smlq.top());
smlq.pop();
Oput(bigq.top());
putchar('\n');
}
else
{
bigq.push(t);
smlq.push(-bigq.top());
bigq.pop();
}
}
return 0;
}
//总之插入操作要先插入另一个堆再弹出top插入这一个堆(无视常数
```
### 并查集
> P3367 【模板】并查集
普通并查集
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 10010
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int n, m;
int pre[MAXN];
il void ini_f(int n)
{
for(rg int i=1 ; i<=n ; ++i)
pre[i] = i;
}
int find_f(int x)
{
if(pre[x] == x) return x;
return find_f(pre[x]);
}
il void union_f(int u, int v)
{
int fu = find_f(u), fv = find_f(v);
if(fu != fv) pre[fu] = fv;
}
il bool judge_f(int u, int v)
{
return find_f(u) == find_f(v);
}
int main()
{
Iput(n), Iput(m);
ini_f(n);
for(rg int i=1 ; i<=m ; ++i)
{
int op, x, y;
Iput(op), Iput(x), Iput(y);
if(op == 1)
{
union_f(x, y);
}
else
{
putchar(judge_f(x, y) ? 'Y' : 'N');
putchar('\n');
}
}
return 0;
}
```
自己口糊的按秩合并+路径压缩
```cpp
#include<cstdio>
#include<iostream>
#include<cstring>
#define il inline
#define rg register
#define MAXN 10010
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int n, m;
int pre[MAXN];
il void ini_f()
{
memset(pre, -1, sizeof pre);
}
int find_f(int x)
{
if(pre[x] < 0) return x;
return pre[x] = find_f(pre[x]);
}
il void union_f(int a, int b)
{
int fa = find_f(a), fb = find_f(b);
if(fa == fb) return ;
if(pre[fa] < pre[fb]) pre[fa] += pre[fb], pre[fb] = fa;
else pre[fb] += pre[fa], pre[fa] = fb;
}
il bool judge_f(int u, int v)
{
return find_f(u) == find_f(v);
}
int main()
{
Iput(n), Iput(m);
ini_f(); //注意
for(rg int i=1 ; i<=m ; ++i)
{
int op, x, y;
Iput(op), Iput(x), Iput(y);
if(op == 1)
{
union_f(x, y);
}
else
{
putchar(judge_f(x, y) ? 'Y' : 'N');
putchar('\n');
}
}
return 0;
}
```
### 树状数组
普通板子
```cpp
struct TreeArr {
int c[MAXN];
il void add(int pos, int v)
{
for(rg int i=pos ; i<=n ; i+=i&-i)
c[i] += v;
}
il int ask(int pos)
{
int ret = 0;
for(rg int i=pos ; i ; i-=i&-i)
ret += c[i];
return ret;
}
}ta;
```
瞎搞平衡树:
> P3369 【模板】普通平衡树
```cpp
#include<cstdio>
#include<iostream>
#include<algorithm>
#define il inline
#define rg register
#define MAXN 100010
#define ENDL putchar('\n')
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
bool f=false;
while((c=getchar())<'0' || c>'9') if(c=='-') f=true;//这个板子gg了好多次都是因为快读判负
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
if(f) x=-x;
}
template <typename T> void Wri(T x)
{
if(x > 9) Wri(x/10);
putchar(x%10^48);
}
template <typename T> void Oput(T x)
{
if(x < 0) putchar('-'), x=-x;
Wri(x);
}//快写一定要和快读判负一起修改
int n;
struct Qs {
int op, x;
}q[MAXN];
int lsh[MAXN], top;
struct TreeArr {
int c[MAXN];
il void add(int pos)
{
for(rg int i=pos ; i<=top ; i+=i&-i)
++c[i];
}
il void del(int pos)
{
for(rg int i=pos ; i<=top ; i+=i&-i)
--c[i];
}
il int ask(int pos)
{
int ret = 0;
for(rg int i=pos ; i ; i-=i&-i)
ret += c[i];
return ret;
}
il int kth(int k)
{
int p = 0;
for(rg int i=17 ; ~i ; --i)
{
p += 1<<i;
if(p>top || c[p]>=k) //注意c[p](不是c[i]..)
p -= 1<<i;
else
k -= c[p];
}
return p+1;
}
il int lft(int x)
{
return kth(ask(x-1));
}
il int rit(int x)
{
return kth(ask(x)+1);
}
}ta;
int main()
{
Iput(n);
for(rg int i=1 ; i<=n ; ++i)
Iput(q[i].op), Iput(q[i].x), lsh[i] = q[i].x;
sort(lsh+1, lsh+n+1);
top = unique(lsh+1, lsh+n+1) - lsh - 1;
for(rg int i=1 ; i<=n ; ++i)
{
int op=q[i].op, x=q[i].x;
if(op != 4) x = lower_bound(lsh+1, lsh+top+1, x) - lsh;
if(op == 1)
{
ta.add(x);
}
else if(op == 2)
{
ta.del(x);
}
else if(op == 3)
{
Oput(ta.ask(x-1)+1);
ENDL;
}
else if(op == 4)
{
Oput(lsh[ta.kth(x)]);
ENDL;
}
else if(op == 5)
{
Oput(lsh[ta.lft(x)]);
ENDL;
}
else
{
Oput(lsh[ta.rit(x)]);
ENDL;
}
}
return 0;
}
```
### 线段树
普通线段树
> P3373 【模板】线段树 2
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 100010
using namespace std;
typedef long long LL; //注意
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int n, m, p;
LL a[MAXN];
il void Mod(LL &a)
{
if(a>=p) a%=p; //注意:最好不要用减
}
il void add(LL &a, LL b)
{
a += b;
Mod(a);
}
il void mul(LL &a, LL b)
{
a *= b;
Mod(a);
}
struct SGtree {
#define MID int mid=(l+r)>>1
#define L ls(k),l,mid
#define R rs(k),mid+1,r
struct Node {
LL v, la, lm;
}t[MAXN<<2];
il int ls(int k) {return k<<1;}
il int rs(int k) {return k<<1|1;}
il void pu(int k)
{
t[k].v = t[ls(k)].v +t[rs(k)].v;
Mod(t[k].v);
}
void build(int k, int l, int r)
{
t[k].la = 0;
t[k].lm = 1;
if(l == r)
{
t[k].v = a[l];
return ;
}
MID;
build(L);
build(R);
pu(k);
}
il void fa(int k, int l, int r, LL v)
{
add(t[k].v, v*(r-l+1));
add(t[k].la, v);
}
il void fm(int k, LL v)
{
mul(t[k].v, v);
mul(t[k].la, v);
mul(t[k].lm, v);
}
il void pd(int k, int l, int mid, int r)
{
fm(ls(k), t[k].lm);
fm(rs(k), t[k].lm);
fa(L, t[k].la);
fa(R, t[k].la);
t[k].la = 0;
t[k].lm = 1;
}
void modify_a(int k, int l, int r, int li, int ri, LL v)
{
if(li<=l && r<=ri) return fa(k, l, r, v);
MID;
pd(k, l, mid, r);
if(li<=mid) modify_a(L, li, ri, v);
if(mid<ri) modify_a(R, li, ri, v);
pu(k);
}
void modify_m(int k, int l, int r, int li, int ri, LL v)
{
if(li<=l && r<=ri) return fm(k, v);
MID;
pd(k, l, mid, r);
if(li<=mid) modify_m(L, li, ri, v);
if(mid<ri) modify_m(R, li, ri, v);
pu(k);
}
LL query(int k, int l, int r, int li, int ri)
{
if(li<=l && r<=ri) return t[k].v;
MID;
LL ret=0;
pd(k, l, mid, r);
if(li<=mid) add(ret, query(L, li, ri));
if(mid<ri) add(ret, query(R, li, ri));
return ret;
}
}sg;
int main()
{
Iput(n), Iput(m), Iput(p);
for(rg int i=1 ; i<=n ; ++i)
Iput(a[i]);
sg.build(1, 1, n);
for(rg int i=1 ; i<=m ; ++i)
{
int op, x, y, k;
Iput(op), Iput(x), Iput(y);
if(op == 1)
{
Iput(k);
sg.modify_m(1, 1, n, x, y, k);
}
else if(op == 2)
{
Iput(k);
sg.modify_a(1, 1, n, x, y, k);
}
else
{
Oput(sg.query(1, 1, n, x, y));
putchar('\n');
}
}
return 0;
}
```
扫描线
```cpp
```
### zkw线段树
> P3374 【模板】树状数组 1
```cpp
//记得加M啊
struct ZKW {
LL t[MAXN<<3];
int M;
il void pu(int k)
{
t[k] = t[k<<1] + t[k<<1|1];
}
il void build()
{
for(M=1 ; M<n+2 ; M<<=1);
for(rg int i=M+1 ; i<=M+n ; ++i)
Iput(t[i]);
for(rg int i=M ; i ; --i)
pu(i);
}
il void modify(int pos, LL v)
{
for(rg int i=M+pos ; i ; i>>=1)
t[i] += v;
}
il LL query(int l, int r)
{
LL ret = 0;
for(rg int i=M+l-1, j=M+r+1 ; i^j^1 ; i>>=1, j>>=1)
{
if(~i&1) ret += t[i^1];
if(j&1) ret += t[j^1];
}
return ret;
}
}sg;
```
### 分块
> P2357 守墓人
```cpp
#include<cstdio>
#include<iostream>
#include<cmath>
#define il inline
#define rg register
#define int long long
#define MAXN 200010
#define RTN 500
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
bool f=false;
while((c=getchar())<'0' || c>'9') if(c=='-') f=true;
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
if(f) x=-x;
}
template <typename T> void Wri(T x)
{
if(x > 9) Wri(x/10);
putchar(x%10^48);
}
template <typename T> il void Oput(T x)
{
if(x < 0) putchar('-'), x=-x;
Wri(x);
}
int n, m, rtn;
int a[MAXN], lazy[RTN], pos[MAXN], sum[RTN];
il int L(int k)
{
return (pos[k]-1)*rtn+1;
}
il int R(int k)
{
return pos[k]*rtn;
}
il void change(int l, int r, int v)
{
for(rg int i=l, top=min(r, R(l)) ; i<=top ; ++i) a[i]+=v, sum[pos[i]]+=v;
for(rg int i=pos[l]+1 ; i<=pos[r]-1 ; ++i) lazy[i] += v;
if(pos[l] != pos[r])
for(rg int i=L(r) ; i<=r ; ++i)
a[i]+=v, sum[pos[i]]+=v;
}
il int query(int l, int r)
{
int ret = 0;
for(rg int i=l, top=min(r, R(l)) ; i<=top ; ++i) ret += a[i]+lazy[pos[i]];
for(rg int i=pos[l]+1 ; i<=pos[r]-1 ; ++i) ret += sum[i]+rtn*lazy[i];
if(pos[l] != pos[r])
for(rg int i=L(r) ; i<=r ; ++i)
ret += a[i]+lazy[pos[i]];
return ret;
}
signed main()
{
Iput(n), Iput(m);
rtn = sqrt(n);
for(rg int i=1 ; i<=n ; ++i)
{
Iput(a[i]);
pos[i] = (i-1)/rtn+1;
sum[pos[i]] += a[i];
}
for(rg int i=1 ; i<=m ; ++i)
{
int op, l, r, k;
Iput(op);
if(op == 1)
{
Iput(l), Iput(r), Iput(k);
change(l, r, k);
}
else if(op == 2)
{
Iput(k);
a[1] += k;
sum[1] += k;
}
else if(op == 3)
{
Iput(k);
a[1] -= k;
sum[1] -= k;
}
else if(op == 4)
{
Iput(l), Iput(r);
Oput(query(l, r));
putchar('\n');
}
else if(op == 5)
{
Oput(a[1]+lazy[1]);
putchar('\n');
}
}
return 0;
}
```
## 图论
### 最短路
#### Floyd
> P5905 【模板】Johnson 全源最短路(n^3 68分?)
```cpp
for(rg int i=1 ; i<=n ; ++i)
for(rg int j=1 ; j<=n ; ++j)
dis[i][j] = INF;
for(rg int i=1 ; i<=n ; ++i)
dis[i][i] = 0;
for(rg int i=1 ; i<=m ; ++i)
{
int u, v, w;
Iput(u), Iput(v), Iput(w);
Min(dis[u][v], w);
}
for(rg int k=1 ; k<=n ; ++k)
for(rg int i=1 ; i<=n ; ++i)
for(rg int j=1 ; j<=n ; ++j)
{
if(dis[i][k]==INF || dis[k][j]==INF) continue;
Min(dis[i][j], dis[i][k]+dis[k][j]);
}
for(rg int i=1 ; i<=n ; ++i) //负环
if(dis[i][i] < 0)
{
Oput(-1);
return 0;
}
```
#### SPFA(+带容错SLF)
> P3371 【模板】单源最短路径(弱化版)
```cpp
LL dis[MAXN];
#define MAXQ (1<<14)
int q[MAXQ], l=MAXN<<1, r=l-1;
bool in_q[MAXN];
il void spfa()
{
for(rg int i=1 ; i<=n ; ++i)
dis[i] = 0x7fffffff;
dis[s] = 0;
q[++r & MAXQ-1] = s;
in_q[s] = true;
while(l <= r)
{
int u = q[l++ & MAXQ-1];
in_q[u] = false;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x, w = e[i].w;
if(dis[v] > dis[u]+w)
{
dis[v] = dis[u]+w;
if(!in_q[v])
{
if(dis[v] > dis[q[l & MAXQ-1]]+1) q[++r & MAXQ-1] = v;
else q[--l & MAXQ-1] = v;
in_q[v] = true;
}
}
}
}
}
```
#### Dijkstra
> P4779 【模板】单源最短路径(标准版)
```cpp
int dis[MAXN];
priority_queue <pair<int, int> > q;
bool vis[MAXN];
il void dijkstra()
{
memset(dis, 0x3f, sizeof dis);
dis[s] = 0;
q.push(make_pair(0, s));
while(q.size())
{
int u = q.top().second;
q.pop();
if(vis[u]) continue;
vis[u] = true;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x, w = e[i].w;
if(dis[v] > dis[u]+w)
{
dis[v] = dis[u]+w;
q.push(make_pair(-dis[v], v));
}
}
}
}
```
#### Johnson
> P5905 【模板】Johnson 全源最短路
```cpp
#include<cstdio>
#include<iostream>
#include<queue>
#define il inline
#define rg register
#define MAXN 3010
#define MAXM 6010
#define INF 1000000000
using namespace std;
typedef long long LL;
template <typename T> il void Iput(T &x)
{
char c;
bool f=false;
while((c=getchar())<'0' || c>'9') if(c=='-') f=true;
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
if(f) x = -x;
}
template <typename T> void Wri(T x)
{
if(x > 9) Wri(x/10);
putchar(x%10^48);
}
template <typename T> il void Oput(T x)
{
if(x < 0) putchar('-'), x=-x;
Wri(x);
}
struct Edge {
int x, nex, w;
}e[MAXN+MAXM];
int head[MAXN], tote;
il void ae(int u, int v, int w)
{
e[++tote].x = v;
e[tote].w = w;
e[tote].nex = head[u];
head[u] = tote;
}
int n, m;
int h[MAXN];
#define MAXQ (1<<14)
int qs[MAXQ], l=MAXQ<<1, r=l-1;
bool in_q[MAXN];
int len[MAXN];
il bool spfa()
{
for(rg int i=1 ; i<=n ; ++i)
h[i] = INF;
h[0] = 0;
qs[++r & MAXQ-1] = 0;
in_q[0] = true;
while(l <= r)
{
int u = qs[l++ & MAXQ-1];
in_q[u] = false;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x, w = e[i].w;
if(h[v] > h[u]+w)
{
len[v] = len[u] + 1;
if(len[v] > n) return true; //注意应该>n,因为建了一个超级原点
h[v] = h[u]+w;
if(!in_q[v])
{
if(h[v] > h[qs[l & MAXQ-1]]+1) qs[++r & MAXQ-1] = v;
else qs[--l & MAXQ-1] = v;
in_q[v] = true;
}
}
}
}
return false;
}
priority_queue <pair<int, int> > q;
int dis[MAXN];
bool vis[MAXN];
il void dijkstra(int s)
{
for(rg int i=1 ; i<=n ; ++i)
{
dis[i] = INF;
vis[i] = 0;
}
dis[s] = 0;
q.push(make_pair(0, s));
while(q.size())
{
int u = q.top().second;
q.pop();
if(vis[u]) continue;
vis[u] = true;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x, w=e[i].w;
if(dis[v] > dis[u]+w)
{
dis[v] = dis[u]+w;
q.push(make_pair(-dis[v], v));
}
}
}
}
int main()
{
Iput(n), Iput(m);
for(rg int i=1 ; i<=m ; ++i)
{
int u, v, w;
Iput(u), Iput(v), Iput(w);
ae(u, v, w);
}
for(rg int i=1 ; i<=n ; ++i)
ae(0, i, 0);
if(spfa())
{
putchar('-');
putchar('1');
return 0;
}
for(rg int u=1 ; u<=n ; ++u)
for(rg int i=head[u] ; i ; i=e[i].nex)
e[i].w += h[u]-h[e[i].x];
for(rg int u=1 ; u<=n ; ++u)
{
LL ans = 0;
dijkstra(u);
for(rg int i=1 ; i<=n ; ++i)
ans += (LL)i*(dis[i]==INF ? INF : dis[i]-h[u]+h[i]);
Oput(ans);
putchar('\n');
}
return 0;
}
```
#### 差分约束
```cpp
```
### 最小生成树
> P3366 【模板】最小生成树
#### Prim
```cpp
#include<cstdio>
#include<iostream>
#include<cstring>
#define il inline
#define rg register
#define MAXN 5010
#define MAXM 200010
#define INF 0x3f3f3f3f
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
struct Edge {
int x, nex, w;
}e[MAXM<<1];
int head[MAXN], tote;
il void ae(int u, int v, int w)
{
e[++tote].x = v;
e[tote].w = w;
e[tote].nex = head[u];
head[u] = tote;
}
int n, m;
int dis[MAXN];
bool vis[MAXN];
int main()
{
memset(dis, 0x3f, sizeof dis);
Iput(n), Iput(m);
for(rg int i=1 ; i<=m ; ++i)
{
int u, v, w;
Iput(u), Iput(v), Iput(w);
ae(u, v, w);
ae(v, u, w);
}
dis[1] = 0;
for(rg int k=1 ; k<n ; ++k)
{
int u = 0;
for(rg int i=1 ; i<=n ; ++i)
if(!vis[i] && (!u || dis[u]>dis[i]))
u = i;
vis[u] = true;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x, w = e[i].w;
if(!vis[v] && dis[v]>w) //注意dis的含义为最小生成树的边长
dis[v] = w;
}
}
int ans = 0;
for(rg int i=1 ; i<=n ; ++i)
{
if(dis[i] == INF)
{
printf("orz\n");
return 0;
}
ans += dis[i];
}
Oput(ans);
return 0;
}
```
#### Kruskal
```cpp
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define il inline
#define rg register
#define MAXN 5010
#define MAXM 200010
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
struct Edge_k {
int u, v, w;
}e[MAXM];
bool operator < (Edge_k x, Edge_k y)
{
return x.w < y.w;
}
int pre[MAXN];
int find_f(int x)
{
if(pre[x] < 0) return x;
return pre[x] = find_f(pre[x]);
}
il void union_f(int a, int b)
{
int fa=find_f(a), fb=find_f(b);
if(fa == fb) return ;
if(pre[fa] < pre[fb]) pre[fa]+=pre[fb], pre[fb]=fa;
else pre[fb]+=pre[fa], pre[fa]=fb;
}
il bool judge_f(int a, int b)
{
return find_f(a) == find_f(b);
}
int n, m;
int ans;
int main()
{
memset(pre, -1, sizeof pre);
Iput(n), Iput(m);
for(rg int i=1 ; i<=m ; ++i)
Iput(e[i].u), Iput(e[i].v), Iput(e[i].w);
sort(e+1, e+m+1);
for(rg int i=1 ; i<=m ; ++i)
{
int u=e[i].u, v=e[i].v;
if(!judge_f(u, v))
{
union_f(u, v);
ans += e[i].w;
}
}
int fa = find_f(1);
for(rg int i=2 ; i<=n ; ++i)
if(find_f(i) != fa)
{
printf("orz\n");
return 0;
}
Oput(ans);
return 0;
}
```
### Tarjan
#### 割点
> P3388 【模板】割点(割顶)
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 20010
#define MAXM 100010
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
struct Edge {
int x, nex;
}e[MAXM<<1];
int head[MAXN], tote;
il void ae(int u, int v)
{
e[++tote].x = v;
e[tote].nex = head[u];
head[u] = tote;
}
il void Min(int &a, int b)
{
if(a > b) a = b;
}
int n, m;
int root;
int low[MAXN], dfn[MAXN], dtr;
bool cut[MAXN];
void tarjan(int u)
{
int flag = 0;
low[u] = dfn[u] = ++dtr;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x;
if(!dfn[v])
{
tarjan(v);
Min(low[u], low[v]);
if(dfn[u]<=low[v])
{
++flag;
if(u!=root || flag>1)
cut[u] = true;
}
}
else
{
Min(low[u], dfn[v]);
}
}
}
int main()
{
Iput(n), Iput(m);
for(rg int i=1 ; i<=m ; ++i)
{
int u, v;
Iput(u), Iput(v);
ae(u, v);
ae(v, u);
}
for(rg int i=1 ; i<=n ; ++i)
if(!dfn[i])
{
root = i;
tarjan(root);
}
int ans = 0;
for(rg int i=1 ; i<=n ; ++i)
if(cut[i])
++ans;
Oput(ans);
putchar('\n');
for(rg int i=1 ; i<=n ; ++i)
if(cut[i])
Oput(i), putchar(' ');
return 0;
}
```
#### 割边
```cpp
struct Edge {
int x, nex;
}e[MAXM<<1];
int head[MAXN], tote=1; //注意这里初值为1才满足异或配偶性质
il void ae(int u, int v)
{
e[++tote].x = v;
e[tote].nex = head[u];
head[u] = tote;
}
int n, m, ans;
int dfn[MAXN], dtr, low[MAXN];
bool cut[MAXM<<1];
void tarjan(int u, int in_edge) //较割点多一个参数:入边
{
//这里无须特判根节点,无须flag
low[u] = dfn[u] = ++dtr;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x;
if(!dfn[v])
{
tarjan(v, i);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u])
{
cut[i] = cut[i^1] = true;
++ans; //由于搜索树上每条边只被搜索一次,可直接++ans
}
}
else if(i != (in_edge^1)) //注意判反边,防止被父亲更新
{
low[u] = min(low[u], dfn[v]);
}
}
}
int main()
{
...//Input
for(rg int i=1 ; i<=n ; ++i)
if(!dfn[i])
tarjan(i, 0); //这里注意不要写-1等等负数,不满足异或性质
Oput(ans);
return 0;
}
```
#### 强连通分量:缩点
> P3387 【模板】缩点
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 10010
#define MAXM 100010
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
struct Star {
struct Edge {
int x, nex;
}e[MAXM];
int head[MAXN], tote;
il void ae(int u, int v)
{
e[++tote].x = v;
e[tote].nex = head[u];
head[u] = tote;
}
}Nor, Scc;
il void Min(int &a, int b)
{
if(a > b) a = b;
}
il void Max(int &a, int b)
{
if(a < b) a = b;
}
int n, m;
int w[MAXN];
int low[MAXN], dfn[MAXN], dtr;
int scc, bel[MAXN], stk[MAXN], top, wscc[MAXN];
bool in_s[MAXN];
void tarjan(int u)
{
low[u] = dfn[u] = ++dtr;
stk[++top] = u;
in_s[u] = true;
for(rg int i=Nor.head[u] ; i ; i=Nor.e[i].nex)
{
int v = Nor.e[i].x;
if(!dfn[v])
{
tarjan(v);
Min(low[u], low[v]);
}
else if(in_s[v])
{
Min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u])
{
int t;
++scc;
do
{
t = stk[top--];
in_s[t] = false;
bel[t] = scc;
wscc[scc] += w[t];
}while(t != u);
}
}
int dp[MAXN], ans;
int main()
{
Iput(n), Iput(m);
for(rg int i=1 ; i<=n ; ++i)
Iput(w[i]);
for(rg int i=1 ; i<=m ; ++i)
{
int u, v;
Iput(u), Iput(v);
Nor.ae(u, v);
}
for(rg int i=1 ; i<=n ; ++i)
if(!dfn[i])
tarjan(i);
for(rg int u=1 ; u<=n ; ++u)
for(rg int i=Nor.head[u] ; i ; i=Nor.e[i].nex)
{
int v = Nor.e[i].x;
if(bel[u] != bel[v])
Scc.ae(bel[u], bel[v]);
}
for(rg int u=scc ; u ; --u)
{
dp[u] += wscc[u];
Max(ans, dp[u]);
for(rg int i=Scc.head[u] ; i ; i=Scc.e[i].nex)
Max(dp[Scc.e[i].x], dp[u]);
}
Oput(ans);
return 0;
}
```
### 树
#### 直径
```cpp
```
#### 倍增
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 500010
#define MAXM 500010
#define LOGN 19
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
struct Edge {
int x, nex;
}e[MAXM<<1];
int head[MAXN], tote;
il void ae(int u, int v)
{
e[++tote].x = v;
e[tote].nex = head[u];
head[u] = tote;
}
int n, m, s;
int fa[MAXN][LOGN+1], dep[MAXN]; //注意+1
void get_fa(int u, int f)
{
dep[u] = dep[f] + 1;
fa[u][0] = f;
for(rg int i=1 ; i<=LOGN ; ++i)
fa[u][i] = fa[fa[u][i-1]][i-1];
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x;
if(v == f) continue;
get_fa(v, u);
}
}
il int lca(int u, int v)
{
if(dep[u] < dep[v]) swap(u, v);
for(rg int i=LOGN ; ~i ; --i)
if(dep[fa[u][i]] >= dep[v])
u = fa[u][i];
if(u == v) return u;
for(rg int i=LOGN ; ~i ; --i)
if(fa[u][i] != fa[v][i])
{
u = fa[u][i];
v = fa[v][i];
}
return fa[u][0];
}
int main()
{
Iput(n), Iput(m), Iput(s);
for(rg int i=1 ; i<n ; ++i)
{
int u, v;
Iput(u), Iput(v);
ae(u, v);
ae(v, u);
}
get_fa(s, s);
for(rg int i=1 ; i<=n ; ++i)
{
int u, v;
Iput(u), Iput(v);
Oput(lca(u, v));
putchar('\n');
}
return 0;
}
```
#### 树剖
> P3384 【模板】轻重链剖分
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 100010
#define int long long
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
struct Edge {
int x, nex;
}e[MAXN<<1];
int head[MAXN], tote;
il void ae(int u, int v)
{
e[++tote].x = v;
e[tote].nex = head[u];
head[u] = tote;
}
int n, m, r, p;
int w[MAXN];
il void Mod(int &a)
{
if(a >= p) a %= p;
}
il void add(int &a, int b)
{
a += b;
Mod(a);
}
struct SGtree {
#define MID int mid=(l+r)>>1
#define L ls(k),l,mid
#define R rs(k),mid+1,r
int a[MAXN];
struct Node {
int v, lazy;
}t[MAXN<<2];
il int ls(int k) {return k<<1;}
il int rs(int k) {return k<<1|1;}
il void pu(int k)
{
t[k].v = t[ls(k)].v + t[rs(k)].v;
Mod(t[k].v); //注意取模
}
void build(int k, int l, int r)
{
if(l == r)
{
t[k].v = a[l];
Mod(t[k].v);
return ;
}
MID;
build(L);
build(R);
pu(k);
}
il void f(int k, int l, int r, int v)
{
add(t[k].v, v*(r-l+1));
add(t[k].lazy, v);
}
il void pd(int k, int l, int mid, int r)
{
if(!t[k].lazy) return ;
f(L, t[k].lazy);
f(R, t[k].lazy);
t[k].lazy = 0;
}
void modify(int k, int l, int r, int li, int ri, int v)
{
if(li<=l && r<=ri) return f(k, l, r, v);
MID;
pd(k, l, mid, r);
if(li<=mid) modify(L, li, ri, v);
if(mid<ri) modify(R, li, ri, v);
pu(k);
}
int query(int k, int l, int r, int li, int ri)
{
if(li<=l && r<=ri) return t[k].v;
MID, ret=0;
pd(k, l, mid, r);
if(li<=mid) add(ret, query(L, li, ri));
if(mid<ri) add(ret, query(R, li, ri)); //注意取模:写add
return ret;
}
}sg;
struct Decomposition {
int siz[MAXN], dep[MAXN], wson[MAXN], fa[MAXN], top[MAXN], dfn[MAXN], dtr;
void dfs1(int u, int f)
{
fa[u] = f;
dep[u] = dep[f] + 1;
siz[u] = 1;
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x;
if(v == f) continue;
dfs1(v, u);
siz[u] += siz[v];
if(!wson[u] || siz[wson[u]]<siz[v])
wson[u] = v;
}
}
void dfs2(int u, int topf)
{
top[u] = topf;
dfn[u] = ++dtr;
sg.a[dtr] = w[u];
if(!wson[u]) return ; //注意处理重儿子
dfs2(wson[u], topf);
for(rg int i=head[u] ; i ; i=e[i].nex)
{
int v = e[i].x;
if(v==fa[u] || v==wson[u]) continue;
dfs2(v, v);
}
}
il void modify_lca(int u, int v, int val)
{
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
sg.modify(1, 1, n, dfn[top[u]], dfn[u], val);
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u, v);
sg.modify(1, 1, n, dfn[u], dfn[v], val);
}
il int query_lca(int u, int v)
{
int ret = 0;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
add(ret, sg.query(1, 1, n, dfn[top[u]], dfn[u]));
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u, v); //想清楚那个更浅
add(ret, sg.query(1, 1, n, dfn[u], dfn[v]));
return ret;
}
il void modify_son(int x, int val)
{
sg.modify(1, 1, n, dfn[x], dfn[x]+siz[x]-1, val);
}
il int query_son(int x)
{
return sg.query(1, 1, n, dfn[x], dfn[x]+siz[x]-1);
}
}dc;
signed main()
{
Iput(n), Iput(m), Iput(r), Iput(p);
for(rg int i=1 ; i<=n ; ++i)
Iput(w[i]);
for(rg int i=1 ; i<n ; ++i) //n-1边
{
int u, v;
Iput(u), Iput(v);
ae(u, v);
ae(v, u);
}
dc.dfs1(r, r); //remember
dc.dfs2(r, r);
sg.build(1, 1, n);
for(rg int i=1 ; i<=m ; ++i)
{
int op, x, y, z;
Iput(op);
if(op == 1)
{
Iput(x), Iput(y), Iput(z);
dc.modify_lca(x, y, z);
}
else if(op == 2)
{
Iput(x), Iput(y);
Oput(dc.query_lca(x, y));
putchar('\n');
}
else if(op == 3)
{
Iput(x), Iput(z);
dc.modify_son(x, z);
}
else
{
Iput(x);
Oput(dc.query_son(x));
putchar('\n');
}
}
return 0;
}
```
### 欧拉路
> P1341 无序字母对
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 'z'
#define MINN 'A'
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int n;
int mp[MAXN+10][MAXN+10];
int deg[MAXN+10];
int stk[10000], top;
void dfs(int u)
{
for(rg int i=MINN ; i<=MAXN ; ++i)
if(mp[u][i])
{
--mp[u][i];
--mp[i][u];
dfs(i);
}
stk[++top] = u;
}
int main()
{
Iput(n);
for(rg int i=1 ; i<=n ; ++i)
{
int u, v;
while(!( ((u=getchar())>='a'&&u<='z') || (u>='A'&&u<='Z') ));
while(!( ((v=getchar())>='a'&&v<='z') || (v>='A'&&v<='Z') ));
++mp[u][v];
++mp[v][u];
++deg[u];
++deg[v];
}
int ctr=0, s=0;
for(rg int i=MINN ; i<=MAXN ; ++i)
if(deg[i]&1)
{
if(!s) s=i;
++ctr;
}
if(!ctr)
{
for(rg int i=MINN ; i<=MAXN ; ++i)
if(deg[i])
{
if(!s) s=i;
break;
}
}
if(ctr!=0 && ctr!=2)
{
printf("No Solution\n");
return 0;
}
dfs(s);
if(top != n+1)
{
printf("No Solution\n");
return 0;
}
for(rg int i=top ; i ; --i)
putchar(stk[i]);
return 0;
}
```
## 数学相关
### 快速幂
> P1226 【模板】快速幂||取余运算
多取模
```cpp
int a, k, p;
il void Mod(int &a)
{
if(a >= p) a %= p;
}
il void mul(int &a, int b)
{
a *= b;
Mod(a);
}
il int qpow(int a, int k)
{
int ret = 1;
while(k)
{
if(k&1) mul(ret, a);
mul(a, a);
k >>= 1;
}
return ret%p; //不模的话这样会挂:x^0 mod 1=1
}
signed main()
{
Iput(a), Iput(k), Iput(p);
printf("%lld^%lld mod %lld=%lld\n", a, k, p, qpow(a, k));
return 0;
}
```
### 慢速乘
```cpp
int a, k, p;
il void Mod(int &a)
{
if(a >= p) a %= p;
}
il void add(int &a, int b)
{
a += b;
Mod(a);
}
il void mul(int &a, int b)
{
int ret = 0;
while(b)
{
if(b&1) add(ret, a);
add(a, a);
b >>= 1;
}
a = ret;
}
il int qpow(int a, int k)
{
int ret = 1;
while(k)
{
if(k&1) mul(ret, a);
mul(a, a);
k >>= 1;
}
return ret%p;
}
signed main()
{
Iput(a), Iput(k), Iput(p);
printf("%lld^%lld mod %lld=%lld\n", a, k, p, qpow(a, k));
return 0;
}
```
### 线性筛素数
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 100000010
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int N, q;
int prime[MAXN], mdiv[MAXN], tot;
il void get_prime(int n)
{
for(rg int i=2 ; i<=n ; ++i)
{
if(!mdiv[i])
{
prime[++tot] = i;
mdiv[i] = i;
}
for(rg int j=1 ; j<=tot&&prime[j]*i<=n ; ++j)
{
mdiv[i*prime[j]] = prime[j];
if(mdiv[i] == prime[j]) break;
}
}
}
int main()
{
Iput(N), Iput(q);
get_prime(N);
for(rg int i=1 ; i<=q ; ++i)
{
int t;
Iput(t);
Oput(prime[t]);
putchar('\n');
}
return 0;
}
```
### gcd
> P4549 【模板】裴蜀定理
```cpp
il int gcd(int a, int b)
{
while(a^=b^=a^=b%=a);
return b;
}
```
### exgcd
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define int long long
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
bool f=false;
while((c=getchar())<'0' || c>'9') if(c=='-') f=true;
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
if(f) x=-x;
}
template <typename T> void Wri(T x)
{
if(x > 9) Wri(x/10);
putchar(x%10^48);
}
template <typename T> il void Oput(T x)
{
if(x < 0) putchar('-'), x=-x;
Wri(x);
}
int T;
void exgcd(int a, int b, int &g, int &x, int &y)
{
if(!b)
{
x=1, y=0, g=a;
}
else
{
exgcd(b, a%b, g, y, x);
y -= x*(a/b);
}
}
signed main()
{
Iput(T);
for(rg int rp=1 ; rp<=T ; ++rp)
{
int a, b, c;
Iput(a), Iput(b), Iput(c);
int x, y, g;
exgcd(a, b, g, x, y);
if(c%g)
{
Oput(-1);
putchar('\n');
continue;
}
a /= g;
b /= g;
// c /= g;
x *= c/g;
y *= c/g;
int xmin = (x%b+b)%b;
int ymin = (y%a+a)%a;
if(!xmin) xmin += b;
if(!ymin) ymin += a;
a *= g;
b *= g;
// c *= g;
int xmax = (c-b*ymin)/a;
int ymax = (c-a*xmin)/b;
a /= g;
b /= g;
if(xmax<=0 || ymax<=0)
{
Oput(xmin);
putchar(' ');
Oput(ymin);
putchar('\n');
}
else
{
Oput((xmax-xmin)/b+1);
putchar(' ');
Oput(xmin);
putchar(' ');
Oput(ymin);
putchar(' ');
Oput(xmax);
putchar(' ');
Oput(ymax);
putchar('\n');
}
}
return 0;
}
```
### 高斯消元
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 55
using namespace std;
typedef double DB;
il DB Abs(DB x)
{
if(x < 0) return -x;
return x;
}
il bool e0(DB x)
{
return Abs(x) < 1e-7;
}
int n;
DB a[MAXN][MAXN];
il void gauss()
{
int rank = 0;
for(rg int c=1 ; c<=n ; ++c)
{
int pos = 0;
for(rg int r=rank+1 ; r<=n ; ++r)
if(!e0(a[r][c]))
{
pos = r;
break;
}
if(!pos) continue;
++rank;
for(rg int i=c ; i<=n+1 ; ++i)
swap(a[rank][i], a[pos][i]);
for(rg int r=1 ; r<=n ; ++r)
{
if(r == rank) continue;
DB t = -a[r][c]/a[rank][c];
for(rg int i=c ; i<=n+1 ; ++i)
a[r][i] += t*a[rank][i];
}
}
for(rg int i=rank+1 ; i<=n ; ++i)
if(!e0(a[i][n+1]))
{
putchar('-');
putchar('1');
return ;
}
if(rank < n)
{
putchar('0');
return ;
}
for(rg int i=1 ; i<=n ; ++i)
printf("x%d=%.2lf\n", i, a[i][n+1]/a[i][i]);
}
int main()
{
scanf("%d", &n);
for(rg int i=1 ; i<=n ; ++i)
for(rg int j=1 ; j<=n+1 ; ++j)
scanf("%lf", &a[i][j]);
gauss();
return 0;
}
```
### 矩阵快速幂
```cpp
#include<cstdio>
#include<iostream>
#include<cstring>
#define il inline
#define rg register
#define MAXN 110
#define MOD 1000000007
#define int long long
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
bool f=false;
while((c=getchar())<'0' || c>'9') if(c=='-') f=true;
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
if(f) x=-x;
}
template <typename T> void Wri(T x)
{
if(x > 9) Wri(x/10);
putchar(x%10^48);
}
template <typename T> il void Oput(T x)
{
if(x < 0) putchar('-'), x=-x;
Wri(x);
}
int n, k;
struct Sqr {
int a[MAXN][MAXN];
Sqr() {memset(a, 0, sizeof a);}
}org;
Sqr operator * (Sqr x, Sqr y)
{
Sqr ret;
for(rg int k=1 ; k<=n ; ++k)
for(rg int i=1 ; i<=n ; ++i)
for(rg int j=1 ; j<=n ; ++j)
{
ret.a[i][j] += x.a[i][k]*y.a[k][j]%MOD;
ret.a[i][j] %= MOD;
}
return ret;
}
Sqr qpow(Sqr x, int k)
{
Sqr ret;
for(rg int i=1 ; i<=n ; ++i)
ret.a[i][i] = 1;
while(k)
{
if(k&1) ret = ret*x;
x = x*x;
k >>= 1;
}
return ret;
}
signed main()
{
Iput(n), Iput(k);
for(rg int i=1 ; i<=n ; ++i)
for(rg int j=1 ; j<=n ; ++j)
Iput(org.a[i][j]);
org = qpow(org, k);
for(rg int i=1 ; i<=n ; ++i)
for(rg int j=1 ; j<=n ; ++j)
Oput((org.a[i][j]%MOD+MOD)%MOD), putchar(j==n?'\n':' ');
return 0;
}
```
组合数的求法
高中数学..
## 字符串
### Hash
> P3370 【模板】字符串哈希
bitset开桶
```cpp
#include<cstdio>
#include<iostream>
#include<bitset>
#define il inline
#define rg register
#define BASE 131
#define MOD 1000000007
using namespace std;
typedef long long LL;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int n;
bitset <MOD> Hash; //120MB
int ans;
int main()
{
Iput(n);
for(rg int i=1 ; i<=n ; ++i)
{
char c;
while(!( ((c=getchar())>='0'&&c<='9') || (c>='a'&&c<='z') || (c>='A'&&c<='Z') ));
LL ret = c;
while( ((c=getchar())>='0'&&c<='9') || (c>='a'&&c<='z') || (c>='A'&&c<='Z') )
{
ret = ret*BASE+c;
if(ret >= MOD) ret %= MOD;
}
if(!Hash[ret])
{
Hash[ret] = 1;
++ans;
}
}
Oput(ans);
return 0;
}
```
离散化
```cpp
#include<cstdio>
#include<algorithm>
#define rg register
#define il inline
#define MAXN 10010
#define Base 26
#define MOD 2147483629
using namespace std;
typedef long long LL;
LL a[MAXN];
il LL hash(char c[])
{
LL ans = 1ll;
for(rg int i=0 ; c[i]!='\0' ; ++i)
{
ans = ans*26 + c[i];
if(ans > MOD)
ans %= MOD;
}
return ans;
}
int main()
{
int n, ans=0;
scanf("%d", &n);
for(rg int i=1 ; i<=n ; ++i)
{
char c[1510];
scanf("%s", c);
a[i] = hash(c);
}
sort(a+1, a+1+n);
printf("%d", unique(a+1, a+1+n) - a - 1);
return 0;
}
```
哈希表
```cpp
#include<cstdio>
#include<iostream>
#include<string>
#define il inline
#define rg register
#define MAXN 10010
#define BASE 131
#define MOD 1000003
using namespace std;
typedef long long LL;
struct Edge {
string s;
int nex;
}e[MAXN];
int head[MOD], tote;
il void ae(int Hash, string s)
{
e[++tote].s = s;
e[tote].nex = head[Hash];
head[Hash] = tote;
}
int n, ans;
int main()
{
cin >> n;
for(rg int i=1 ; i<=n ; ++i)
{
string t;
cin >> t;
LL ret = 0;
for(string::iterator it=t.begin() ; it!=t.end() ; ++it)
{
ret = ret*BASE+(*it);
if(ret >= MOD) ret %= MOD;
}
bool flag = false;
for(rg int j=head[ret] ; j ; j=e[j].nex)
if(e[j].s == t)
{
flag = true;
break;
}
if(!flag)
{
ae(ret, t);
++ans;
}
}
cout << ans;
return 0;
}
```
单字符串Hash
```cpp
il void make_base(int l)
{
b[0] = 1;
for(rg int i=1 ; i<=l ; ++i)
{
b[i] = b[i-1] * base % MOD;
if(b[i] < 0) b[i] += MOD;
}
}
il void make_hash(int l)
{
for(rg int i=1 ; i<=l ; ++i)
{
h[i] = (h[i-1] * base + str[i]-'a') % MOD;
if(h[i] < 0) h[i] += MOD;
}
}
il int hash(int l, int r)
{
return ((h[r] - b[r-l+1]*h[l-1])%MOD + MOD)%MOD;
}
```
### Trie
```cpp
struct Trie {
struct Node {
int ch[26], ctr;
}t[MAXN*MAXL]; //注意大小
int tot;
il void insert(char s[])
{
int p = 0;
int len=strlen(s);
for(rg int i=0 ; i<len ; ++i)
{
int c = s[i]-'a';
if(!t[p].ch[c]) t[p].ch[c] = ++tot;
p = t[p].ch[c];
}
++t[p].end;
}
il int find(char s[])
{
int p = 0;
int len=strlen(s);
for(rg int i=0 ; i<len ; ++i)
{
int c = s[i]-'a';
if(!t[p].ch[c]) return 0;
p = t[p].ch[c];
}
return t[p].end;
}
}trie;
```
### KMP
```cpp
#include<cstdio>
#include<iostream>
#include<cstring>
#define il inline
#define rg register
#define MAXN 1000010
using namespace std;
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
char s[MAXN], t[MAXN];
int ls, lt;
int fail[MAXN];
int main()
{
scanf("%s%s", t+1, s+1); //注意1下标开始
lt = strlen(t+1);
ls = strlen(s+1);
for(rg int i=2, j=0 ; i<=ls ; ++i) //fail[1] = 0;
{
while(j && s[i]!=s[j+1]) j = fail[j];
if(s[i] == s[j+1]) ++j;
fail[i] = j;
}
for(rg int i=1, j=0 ; i<=lt ; ++i) //从1开始
{
while(j && t[i]!=s[j+1]) j = fail[j];
if(t[i] == s[j+1]) ++j;
if(j == ls)
{
Oput(i-ls+1);
putchar('\n');
}
}
for(rg int i=1 ; i<=ls ; ++i)
Oput(fail[i]), putchar(' ');
return 0;
}
```
### Manacher
```cpp
#include<cstdio>
#include<iostream>
#define il inline
#define rg register
#define MAXN 11000010
using namespace std;
template <typename T> il void Iput(T &x)
{
char c;
while((c=getchar())<'0' || c>'9');
x = c^48;
while((c=getchar())>='0' && c<='9') x = (x<<1) + (x<<3) + (c^48);
}
template <typename T> void Oput(T x)
{
if(x > 9) Oput(x/10);
putchar(x%10^48);
}
int n;
char s[MAXN];
int mid, mp; //mp为开区间
int ans;
int p[MAXN]; //包括自己的翼长
int main()
{
s[0] = 1; //注意这个
do
{
n += 2;
s[n] = getchar();
}while(s[n]>='a' && s[n]<='z');
s[n--] = 2; //注意这个
for(rg int i=1 ; i<=n ; ++i)
{
p[i] = i<mp ? min(mp-i, p[(mid<<1)-i]) : 1;
while(s[i-p[i]] == s[i+p[i]]) ++p[i];
if(i+p[i] > mp)
{
mp = i+p[i];
mid = i;
}
ans = max(ans, p[i]);
}
Oput(ans-1); //注意减1!!
return 0;
}
```
### 最小表示法
```cpp
```
## 其他知识和技巧
### 离散化
eg:
> P1496 火烧赤壁
```cpp
Iput(n);
for(rg int i=1 ; i<=n ; ++i)
{
Iput(a[i].l), Iput(a[i].r);
lsh[i] = a[i].l;
lsh[i+n] = a[i].r;
}
sort(lsh+1, lsh+(n<<1)+1); //注意离散化数组长度,并且记得开够
int len = unique(lsh+1, lsh+(n<<1)+1) - lsh - 1;
for(rg int i=1 ; i<=n ; ++i)
{
int ll = lower_bound(lsh+1, lsh+len+1, a[i].l) - lsh;
int rr = lower_bound(lsh+1, lsh+len+1, a[i].r) - lsh;
for(rg int j=ll ; j<rr ; ++j)
bt[j] = true;
}
```
### 康拓展开
```cpp
```
### 随机化算法