#图论
#1 - 费用流
struct E {
int to,flow,cast,next;
E(int to=0,int flow=0,int cast=0,int next=0):
to(to),flow(flow),cast(cast),next(next){}
}g[N*N];
int fr[N],tot=1; // !!
void Add(int from,int to,int flow,int cast) {
//cout<<"E"<<from<<" "<<to<<" "<<flow<<" "<<cast<<"\n";
g[++tot] = E(to,flow,cast,fr[from]);
fr[from] = tot;
g[++tot] = E(from,0,-cast,fr[to]);
fr[to] = tot;
}
int d[N],fl[N],p[N],inq[N],st,ed,Cast,n,m;
bool spfa() {
static int idd = 0; ++idd;
memset(d,127/3,sizeof(d[0])*(ed+6));
queue<int> q;
q.push(st); d[st] = 0; inq[st] = idd; fl[st] = 1e9;
while(q.size()) {
int t = q.front(); q.pop(); inq[t] = 0;
for (int i = fr[t]; i; i = g[i].next) {
int to = g[i].to;
if(d[to] > d[t]+g[i].cast && g[i].flow) {
d[to] = d[t]+g[i].cast;
fl[to] = min(fl[t],g[i].flow);
p[to] = i;
if(inq[to] != idd) {
inq[to] = idd;
q.push(to);
}
}
}
}
return d[ed] != d[ed+1];
}
void mcmf() {
Cast += fl[ed]*d[ed];
for(int t = ed,e = p[t]; t != st; ) {
g[e].flow -= fl[ed];
g[e^1].flow += fl[ed];
t = g[e^1].to;
e = p[t];
}
}
#2 - 最大流
bool bfs() {
memset(d,-1,sizeof(d[0])*(ed+10));
queue<int> q;
q.push(st); d[st] = 0;
while(q.size()) {
int t = q.front(); q.pop();
for (int i = fr[t]; i; i = g[i].next) {
int to = g[i].to;
if(d[to] == -1 && g[i].flow) {
d[to] = d[t]+1;
q.push(to);
}
}
}
return d[ed] != -1;
}
int dfs(int t,int mf) {
if(t == ed || mf == 0) return mf;
int tmp = 0;
for (int &i = cur[t]; i&&mf; i = g[i].next) {
if(g[i].flow == 0 || d[g[i].to] != d[t]+1) continue;
int f = dfs(g[i].to,min(mf,g[i].flow));
mf -= f; tmp += f;
g[i].flow -= f; g[i^1].flow += f;
}
if(!tmp) d[t] = -1;
return tmp;
}
int Dinic(int s,int t) {
st = s; ed = t;int max_flow = 0;
while(bfs()) {
copy(fr,fr+ed+2,cur);
max_flow += dfs(st,inf);
}
return max_flow;
}
#3 - tarjan强连通分量
void tarjan(int x) {
dfn[x] = low[x] = ++id;
stack[++top] = x;
ins[x] = true;
for (int i = fr[x]; i; i = g[i].next) {
if(dfn[g[i].to] == -1) {
tarjan(g[i].to);
low[x] = min(low[x],low[g[i].to]);
} else if(ins[g[i].to])
low[x] = min(low[x],dfn[g[i].to]);
}
if(low[x] == dfn[x]) {
cnt++;
while(stack[top] != x) {
f[stack[top]] = cnt;
ins[stack[top]] = false;
top--;
}
ins[x] = false;
f[stack[top--]] = cnt;
}
}
#4-*2-sat
void Add(int ta,int a,int tb,int b) {
a = a<<1|ta; b = b<<1|tb;
g[a^1].push_back(b);
g[b^1].push_back(a);
}
bool Mark[N];int st[N],top,n,m,k;
bool dfs(int t) {
if(Mark[t]) return 1;
if(Mark[t^1]) return 0;
Mark[st[++top] = t] = true;
for (int i = 0; i < g[t].size(); i++)
if(!dfs(g[t][i])) return false;
return true;
}
bool pd() {
for (int i = 2; i <= n*2; i+=2,top = 0)
if(!Mark[i] && !Mark[i^1]) {
if(!dfs(i)) {
for( ; top; Mark[st[top--]] = 0);
if(!dfs(i^1)) return false;
}
}
return true;
}
#5 *k-short
struct No{
int t,dis;No(int t,int dis):t(t),dis(dis){}
bool operator < (const No &lhs) const {return dis+d[t] > lhs.dis+d[lhs.t];}
};
int cnt[N];
priority_queue<No> q1;
void Astar(int st,int ed,int k) {
init();
q1.push(No(st,0));
while(q1.size()) {
No t = q1.top();q1.pop();
if(t.t == ed) {k--;if(k==0) return;}
for (int i = fr[t.t]; i; i = g[i].next)
q1.push(No(g[i].to,t.dis+g[i].w));
}
while(k--) printf("-1\n");
}
字符串
#1 - kmp
// cin >> s+1;
void getfail() {
int j = 0; f[1] = 0;
for (int i = 2; i <= len1; i++) {
while(j && s1[j+1] != s1[i]) j = f[j];
if(s1[j+1] == s1[i]) j++;
f[i] = j;
}
}
void kmp() {
int j = 0;
for (int i = 1; i <= len2; i++) {
while(j && s1[j+1] != s2[i]) j = f[j];
if(s1[j+1] == s2[i]) j++;
if(j == len1) { j = f[j]; tot++;}
}
}
#2 - trie树&AC自动机
struct Trie {int Next[2];bool End;}a[N];
int Fail[N];
int tot = 0,ans;
void Ins(char *s) {
int len = strlen(s),now = 0;
for (int i = 0; i < len; i++) {
int c = s[i]-'0';
if(!a[now].Next[c]) a[now].Next[c] = ++tot;
now = a[now].Next[c];
}
a[now].End = true;
}
void Get_fail() {
static queue<int> q;
for (int i = 0; i < 2; i++)
if(a[0].Next[i]) q.push(a[0].Next[i]);
while(q.size()) {
int t = q.front(); q.pop();
a[t].End |= a[Fail[t]].End;
for (int i = 0; i < 2; i++) {
if(!a[t].Next[i]) {a[t].Next[i] = a[Fail[t]].Next[i];continue;}
Fail[a[t].Next[i]] = a[Fail[t]].Next[i];
q.push(a[t].Next[i]);
}
}
}
#3 - 后缀数组
void radix(int *s,int *a,int *b,int n,int m) {
static int c[N];
memset(c,0,sizeof(c[0])*(m+2));
for (int i = n-1; i >= 0; --i) ++c[s[a[i]]];
for (int i = 1; i <= m; ++i) c[i] += c[i-1];
for (int i = n-1; i >= 0; --i) b[--c[s[a[i]]]] = a[i]; // rank 0 - n-1
}
void suffix(int *s,int *sa,int *rk,int n,int m) {
static int a[N],b[N];
for (int i = 0; i < n; ++i) a[i] = i;
radix(s,a,sa,n,m);
rk[sa[0]] = 0;
for (int i = 1; i < n; ++i)
rk[sa[i]] = rk[sa[i-1]]+(s[sa[i-1]]==s[sa[i]]?0:1);
for (int i = 0; 1<<i < n; ++i) {
for (int j = 0; j < n; ++j) {
sa[j] = j;
a[j] = rk[j]+1;
b[j] = j+(1<<i)>=n?0:rk[j+(1<<i)]+1;
}
radix(b,sa,rk,n,n); radix(a,rk,sa,n,n);
rk[sa[0]] = 0;
for (int j = 1; j < n; ++j)
rk[sa[j]] = rk[sa[j-1]]+(a[sa[j]]==a[sa[j-1]]&&b[sa[j]]==b[sa[j-1]]?0:1);
if(rk[sa[n-1]] == n-1) break;
}
}
void calcht(int *s,int *sa,int *rk,int *h,int n) {
int k = 0; h[0] = 0;
for (int i = 0; i < n; ++i) {
if(k) --k;
if(rk[i]) {
while(s[i+k] == s[sa[rk[i]-1]+k]) ++k;
h[rk[i]] = k;
}
}
}
#4 - *回文树
int last,m,tot,sum,slen;
char S[MAXX];
int cnt[MAXX],fail[MAXX],len[MAXX],next[MAXX][26];
//next 小心CE
void init() {
S[0] = '#';
fread(S+1,1,MAXX-10,stdin);
slen = strlen(S+1);
len[0] = 0; len[1] = -1;
tot = 1;last = 0;
fail[0] = 1;
}
int getfail(int x) {
while(S[sum] != S[sum-len[x]-1])
x = fail[x];
return x;
}
void add(char c) {
c -= 'a';
int cur = getfail(last);
if(!next[cur][c]) {
len[++tot] = len[cur]+2;
fail[tot] = next[getfail(fail[cur])][c];
next[cur][c] = tot;
}
last = next[cur][c];
cnt[last]++;
}
inline void work() {
init();
for (sum = 1; sum <= slen; sum++) add(S[sum]);
for(int i = tot; i >= 2; i--) cnt[fail[i]] += cnt[i];
}
#数据结构
#1-fhq treap
#define lh(o) t[o].lch
#define rh(o) t[o].rch
#define L t[o].lch
#define R t[o].rch
#define MP make_pair
typedef pair<int,int> pii;
struct Node {
int lch,rch,siz,r,id;
LL v,lazy;
}t[N];
int tot = 1,pool[N],top;
inline int New_Node(LL v,int id) {
int o = top ? pool[top--]:++tot;
t[o].sum = t[o].v = v; t[o].r = rand(); t[o].siz = 1;
t[o].lch = t[o].rch = 0; t[o].lazy = 0; t[o].id = id;
return o;
}
inline void up(int o) {
t[o].siz = t[L].siz+t[R].siz+1;
}
int mer(int a,int b) {
return !a||!b ? a^b : t[a].r<t[b].r ?
(down(a),rh(a) = mer(rh(a),b),up(a),a):
(down(b),lh(b) = mer(a,lh(b)),up(b),b);
}
inline void get(int &x,int &y,const pii tp) {x=tp.first;y=tp.second;}
pii spl(int o,int k) {
if(!o) return MP(0,0); down(o);
int p = k-t[L].siz-1; return p>=0 ?
(get(R,p,spl(R,p)),up(o),MP(o,p)):
(get(p,L,spl(L,k)),up(o),MP(p,o));
}
#2 - *可并堆
struct Node {
int lch,rch,val,tot;
Node(){}Node(int C):val(C),lch(0),rch(0),tot(1){}
}t[N];
void up(int o) {
t[o].tot = t[t[o].lch].tot+t[t[o].rch].tot+1;
}
int Mer(int a,int b) {
if(!a||!b) return a^b;
if(t[a].val>t[b].val) {
t[a].lch = Mer(t[a].lch,b);
swap(t[a].lch,t[a].rch);
return up(a),a;
} else {
t[b].lch = Mer(t[b].lch,a);
swap(t[b].lch,t[b].rch);
return up(b),b;
}
}
void Pop(int &o) {o = Mer(t[o].lch,t[o].rch);}
#3-*kd_tree
struct Node {
int d[2],ma[2],mi[2],l,r;LL sum,v;
Node(int x=0,int y=0,LL v=0):v(v){sum=v;d[0]=x,d[1]=y;ma[0]=ma[1]=-inf;mi[0]=mi[1]=inf;l=r=sum=0;}
}t[N];
int D,n,m,rt,now,tot;
int xx,yy,x,y;
LL ans;
bool operator < (const Node &a,const Node &b) {return a.d[D] < b.d[D];}
#define L t[o].l
#define R t[o].r
inline void up(int o) {
for (int i = 0; i < 2; i++) {
t[o].ma[i] = max(t[o].d[i],max(t[L].ma[i],t[R].ma[i]));
t[o].mi[i] = min(t[o].d[i],min(t[L].mi[i],t[R].mi[i]));
}
t[o].sum = t[L].sum+t[R].sum+t[o].v;
}
void build(int l,int r,int &o,int cas) {
if(l>r) return; D = cas;
int &mid = o; mid = (l+r)>>1;
nth_element(t+l,t+mid,t+r+1);
build(l,mid-1,L,cas^1); build(mid+1,r,R,cas^1);
up(o);
}
LL query(int o) {
if(!o) return;
if(o != now) downval(ans,dis(o,now));
int miL = Best(L),miR = Best(R);
if(miL < miR) {
if(miL < ans) query(L);
if(miR < ans) query(R);
} else {
if(miR < ans) query(R);
if(miL < ans) query(L);
}
}
void modify(int &o,int cas) {
if(!o) {t[o=++tot] = t[now];up(o);return;}
D = cas;
if(t[now] < t[o]) modify(L,cas^1);
else modify(R,cas^1);
up(o);
}
#4-线段树
//1
void build(int l,int r,int &o) {
t[o = ++tot].l = l; t[o].r = r;
if(l == r) {read(t[o].maxv);return;}
int mid = (l+r) >> 1;
build(l,mid,t[o].lt); build(mid+1,r,t[o].rt);
t[o].maxv = max(t[t[o].lt].maxv,t[t[o].rt].maxv);
}
int query(int l,int r,int o) {
if(!o) return 0;
if(l <= t[o].l && t[o].r <= r) return t[o].maxv;
int mid = (t[o].l+t[o].r) >> 1,tmp = 0;
if(l <= mid) tmp = query(l,r,t[o].lt);
if(r > mid) tmp = max(tmp,query(l,r,t[o].rt));
return tmp;
}
//2
void build() {
for (M=1; M<=n+1; M<<=1);
for (int i = M+1; i <= M+n; i++) read(sum[i]);
for (int i = M-1; i; i--) push_up(i);
}
void add(int x,int v) {
sum[M+x] += v;while(x) push_up(x>>=1);
}
int Sum(int x,int y,int ans = 0) {
for (x=x+M-1,y=y+M+1;x^y^1;x>>=1,y>>=1) {
if(~x&1) ans += sum[x^1];
if(y&1) ans += sum[y^1];
} return ans;
}
#5 - *二维树状数组
void Add(int x,int y,int v) {
for (int i = x; i <= r; i+=lb(i))
for (int j = y; j <= c; j+=lb(j))
S[i][j] += v;
}
int Sum(int x,int y) {
int tmp = 0;
for (int i = x; i >= 1; i-=lb(i))
for (int j = y; j >= 1; j-=lb(j))
tmp += S[i][j];
return tmp;
}
#6 - 点分
void getrt(int t,int fa) {
siz[t] = 1; mx[t] = 0; // bug
for (int i = fr[t]; i; i = g[i].next) {
int to = g[i].to;
if(to == fa || vis[to]) continue;
getrt(to,t);
siz[t] += siz[to];
upval(mx[t],siz[to]);
}
upval(mx[t],Size-siz[t]);
if(mx[t] < mx[rt]) rt = t;
}
int k,ans = inf;
void calc(int t) {}
void slove(int t) {
calc(t);
vis[t] = 1;
for (int i = fr[t]; i; i = g[i].next) {
int to = g[i].to;
if(vis[to]) continue;
//ans -= calc(to);
rt = 0; Size = siz[to]; getrt(to,-1);
slove(rt);
}
}