省选前把板子整理一遍,如果发现有脑抽写错的情况,欢迎各位神犇打脸 :)

数学知识

数论:

//组合数
//C(n,m) 在n个数中选m个的方案数
ll C[N][N];
void get_C(int n)
{
for(int i=1;i<=n;i++)
{
C[i][i]=C[i][0]=1;
for(int j=1;j<i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
}
//欧几里得算法
//(a,b)
ll gcd(ll a,ll b)
{
return b==0? a:gcd(b,a%b);
}
//拓展欧几里得算法
//解同余方程 a*x+b*y = (a,b)
ll exgcd(ll a,ll b,ll& d,ll& x,ll& y)
{
if(!b) { d=a; x=1; y=0; }
else { exgcd(b,a%b,d,y,x); y-=x*(a/b); }
}
//逆元
//a*inv(a,n) = 1 mod n
ll inv(ll a,ll n)
{
ll d,x,y;
exgcd(a,n,d,x,y);
return d==1? (x+n)%n:-1;
}
//lucas定理
//计算较大,有模数的组合数
ll fac[N];
void get_pre(int n)
{
for(int i=1;i<=n;i++)
fac[i]=(fac[i-1]*i)%mod;
}
ll C(ll n,ll m,ll mod)
{
if(n<m) return 0;
if(n<mod&&m<mod)
return fac[n]*inv(fac[m],mod)%mod*inv(fac[n-m],mod)%mod;
return C(n/mod,m/mod,mod)*C(n%mod,m%mod,mod)%mod;
}
//快速幂
//a^p % mod
ll pow(ll a,ll p,ll mod)
{
ll ans=1;
while(p)
{
if(p&1) ans=(ans*a)%mod;
a=(a*a)%mod; p>>=1;
}
return ans;
}
//中国剩余定理
//解线性同余方程组
//sigma{ ai*(1-ai*mi) } % M , ai*mi+wi*y=1
ll a[N],m[N];
ll china(int n)
{
ll M=1,d,x=0,y;
for(int i=1;i<=n;i++) M*=m[i];
for(int i=1;i<=n;i++)
{
ll w=M/m[i];
exgcd(m[i],w,d,d,y);
x=(x+y*w*a[i])%M;
}
return (x+M)%M;
}
//大步小步算法
//计算a^x=b mod n中的最小x
map<int,int> mp;
int BSGS(int a,int b,int n)
{
int m=sqrt(n)+1,e=1,i;
int v=inv(pow(a,m,n),n);
mp[e]=0;
for(i=1;i<m;i++)
{
e=(e*m)%n;
if(!mp.count(e)) mp[e]=i;
}
for(i=0;i<m;i++)
{
if(mp.count(b)) return i*m+mp[b];
b=(b*v)%mod;
}
return -1;
}
//快速筛法求素数表
int su[N],vis[N];
void get_su(int n)
{
for(int i=2;i<=n;i++)
{
if(!vis[i]) su[++su[0]]=i;
for(int j=1;j<=su[0]&&i*su[j]<=n;j++)
{
vis[i*su[j]]=1;
if(i%su[j]==0) break;
}
}
}
//欧拉函数
//phi(n)小于n的数中与n互素的数的个数
ll get_phi(int n)
{
int m=sqrt(n)+1;
ll ans=n;
for(int i=2;i<=m;i++) if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
ll phi[N];
void get_phi_table(int n)
{
phi[1]=1;
for(int i=2;i<=n;i++) if(!phi[i])
{
for(int j=i;j<=n;j+=i)
{
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
//莫比乌斯函数
int mu[N],su[N],vis[N];
void get_mu(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i]) mu[i]=-1,su[++su[0]]=i;
for(int j=1;j<=su[0]&&i*su[j]<=n;j++)
{
vis[i*su[j]]=1;
if(i%su[j]==0) mu[i*su[j]]=0;
else mu[i*su[j]]=-mu[i];
}
}
}
//高斯消元
//解线性方程组
double a[N][N];
void gause(int n)
{
for(int i=1;i<=n;i++)
{
int r=i;
for(int j=i+1;j<=n;j++)
if(fabs(a[j][i])>fabs(a[r][i])) r=i;
for(int j=1;j<=n+1;j++) swap(a[i][j],a[r][j]);
for(int j=n+1;j>=i;j--)
for(int k=i+1;k<=n;k++)
a[k][j]-=a[k][i]/a[i][i]*a[i][j];
}
for(int i=n;i;i--)
{
for(int j=i+1;j<=n;j++)
a[i][n+1]-=a[j][n+1]*a[i][j];
a[i][n+1]/=a[i][i];
}
}

高精度:

int trans(char* s,int st,int ed)
{
int x=0;
for(int i=st;i<ed;i++) x=x*10+s[i]-'0';
return x;
} struct Bign
{
int len; ll N[maxn];
Bign() { len=0; memset(N,0,sizeof(N)); }
Bign(ll num) { *this=num; }
Bign(const char* s) { *this=s; }
void print()
{
printf("%d",N[len-1]);
for(int i=len-2;i>=0;i--)
printf("%08d",N[i]);
puts("");
}
Bign operator = (const ll x)
{
ll num=x;
while(num>base)
{
N[len++]=num%base;
num/=base;
}
if(num) N[len++]=num;
return *this;
}
Bign operator = (char* s)
{
int L=strlen(s);
len=(L-1)/wlen+1;
for(int i=0;i<len;i++)
{
int ed=L-i*wlen;
int st=max(0,ed-wlen);
N[i]=trans(s,st,ed);
}
return *this;
}
bool operator < (const Bign& B) const
{
if(len!=B.len) return len<B.len;
for(int i=len-1;i>=0;i--)
if(N[i]!=B.N[i]) return N[i]<B.N[i];
return 0;
}
bool operator <= (const Bign& B) const
{
return !(B<(*this));
} void clear()
{
while(len>1&&N[len-1]==0) len--;
} Bign operator + (const Bign& B) const
{
Bign C;
C.len=max(len,B.len)+10;
for(int i=0;i<C.len;i++)
{
C.N[i]+=N[i]+B.N[i];
C.N[i+1]+=C.N[i]/base;
C.N[i]%=base;
}
C.clear();
return C;
}
Bign operator - (Bign B)
{
Bign C=*this;
C.len=max(C.len,B.len);
for(int i=0;i<C.len;i++)
{
if(C.N[i]<B.N[i]) C.N[i+1]--,C.N[i]+=base;
C.N[i]=C.N[i]-B.N[i];
}
C.clear();
return C;
}
Bign operator * (const Bign& B) const
{
Bign C;
C.len=len+B.len;
for(int i=0;i<len;i++)
for(int j=0;j<B.len;j++)
C.N[i+j]+=N[i]*B.N[j];
for(int i=0;i<C.len;i++)
{
C.N[i+1]+=C.N[i]/base;
C.N[i]%=base;
}
C.clear();
return C;
}
Bign operator / (const Bign& B)
{
Bign C,F;
C.len=len;
for(int i=len-1;i>=0;i--)
{
F=F*base;
F.N[0]=N[i];
while(B<=F)
{
F=F-B;
C.N[i]++;
}
}
C.clear();
return C;
}
Bign operator % (const Bign& B)
{
Bign r=*this/B;
return *this-r*B;
} }A,B;

  

矩阵乘法:

//矩阵乘法
struct Mat
{
int r,c; ll N[maxn][maxn];
Mat(int r=0,int c=0)
{
this->r=r,this->c=c;
memset(N,0,sizeof(N));
}
Mat operator * (const Mat& B) const
{
Mat C(r,B.c);
for(int i=0;i<r;i++)
for(int j=0;j<B.c;j++)
for(int k=0;k<c;k++)
C.N[i][j]=(C.N[i][j]+N[i][k]*B.N[k][j])%mod;
return C;
}
Mat operator ^ (int p)
{
Mat ans(r,r),tmp=*this;
for(int i=0;i<r;i++) ans.N[i][i]=1;
while(p)
{
if(p&1) ans=ans*tmp;
tmp=tmp*tmp; p>>=1;
}
return ans;
} };

 

数据结构

树状数组:

//树状数组
int C[N],mx;
void Add(int x,int v)
{
for(int i=x;i<=mx;i+=i&-i) C[i]+=v;
}
int query(int x)
{
int ans=0;
for(int i=x;i;i-=i&-i) ans+=C[i];
return ans;
}

  

线段树:

//线段树
//区间加,区间乘,区间求和
int mod;
struct Tnode
{
int u,l,r;
ll sum,add,mul;
void mulv(ll x) {
sum=(sum*x)%mod;
mul=(mul*x)%mod;
add=(add*x)%mod;
}
void addv(ll x) {
sum=(sum+(r-l+1)*x%mod)%mod;
add=(add+x)%mod;
}
void pushdown() ;
void maintain() ;
}T[N];
void Tnode::pushdown() {
if(mul^1) {
T[u<<1].mulv(mul);
T[u<<1|1].mulv(mul);
mul=1;
}
if(add) {
T[u<<1].addv(add);
T[u<<1|1].addv(add);
add=0;
}
}
void Tnode::maintain() {
sum=(T[u<<1].sum+T[u<<1|1].sum)%mod;
} void update(int u,int L,int R,int x,int f)
{
T[u].pushdown();
if(L<=T[u].l&&T[u].r<=R) {
if(!f) T[u].addv(x);
else T[u].mulv(x);
} else {
int mid=T[u].l+T[u].r>>1;
if(L<=mid) update(u<<1,L,R,x,f);
if(mid<R) update(u<<1|1,L,R,x,f);
T[u].maintain();
}
}
ll query(int u,int L,int R)
{
T[u].pushdown();
if(L<=T[u].l&&T[u].r<=R)
return T[u].sum;
else {
int mid=T[u].l+T[u].r>>1;
ll ans=0;
if(L<=mid) ans=(ans+query(u<<1,L,R))%mod;
if(mid<R) ans=(ans+query(u<<1|1,L,R))%mod;
return ans;
}
}
ll a[N]; void build(int u,int l,int r)
{
T[u]=(Tnode){ u,l,r,0,0,1 };
if(l==r) {
T[u].sum=a[l];
} else {
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
T[u].maintain();
}
}

Treap:

//Treap
struct Node
{
Node *ch[2];
int v,r,m,w,s;
Node(int v):v(v) { ch[0]=ch[1]=NULL; r=rand(); s=w=1; }
int cmp(int x) {
if(v==x) return -1;
return x<v? 0:1;
}
void maintain() {
s=w;
if(ch[0]!=NULL) s+=ch[0]->s;
if(ch[1]!=NULL) s+=ch[1]->s;
}
}; void rotate(Node* &o,int d)
{
Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
o->maintain(); k->maintain(); o=k;
}
void insert(Node *&o,int x)
{
if(o==NULL) o=new Node(x);
int d=o->cmp(x);
if(d==-1) o->w++;
else {
insert(o->ch[d],x);
if(o->ch[d]->r > o->r) rotate(o,d^1);
}
o->maintain();
}
void remove(Node *&o,int x)
{
int d=o->cmp(x);
if(d==-1)
{
if(o->s>1) { o->w--; o->maintain(); return ; }
else {
if(o->ch[0]!=NULL&&o->ch[1]!=NULL) {
int d2=o->ch[0]->r > o->ch[1]->r ? 1:0;
rotate(o,d2); remove(o->ch[d2],x);
} else {
if(o->ch[0]!=NULL) o=o->ch[0]; else o=o->ch[1];
delete o;
}
}
} else
remove(o->ch[d],x);
if(o!=NULL) o->maintain();
}
int kth(Node* o,int rk)
{
if(o==NULL) return 0;
int s=o->ch[0]==NULL? 0:o->ch[0]->s;
if(rk==s+1) return o->v;
else if(rk<=s) return kth(o->ch[0],rk);
else return kth(o->ch[1],rk-s-o->w);
}
int rank(Node* o,int x)
{
if(o==NULL) return 0;
int s=o->ch[0]==NULL? 0:o->ch[0]->s;
int d=o->cmp(x);
if(d==-1) return 1;
else if(d==0) return rank(o->ch[0],x);
else return s+o->w+rank(o->ch[1],x);
}
int tmp;
void before(Node* o,int x)
{
if(o==NULL) return ;
if(o->v<x) { tmp=max(tmp,o->v); before(o->ch[1],x); }
else before(o->ch[0],x);
}
void after(Node* o,int x)
{
if(o==NULL) return ;
if(o->v>x) { tmp=min(tmp,o->v); after(o->ch[0],x); }
else after(o->ch[1],x);
}

splay:

//splay自上而下
struct Node
{
Node *ch[2];
int s;
int cmp(int x)
{
int d=x-ch[0]->s;
if(d==1) return -1;
return d<=0? 0:1;
}
void maintain()
{
s=ch[0]->s+ch[1]->s;
}
void pushdown() {}
}mempool[N],*G=mempool; Node* null=new Node();
void rotate(Node* &o,int d)
{
Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d],k->ch[d]=o;
o->maintain(); k->maintain(); o=k;
}
void splay(Node* &o,int k)
{
o->pushdown();
int d=o->cmp(k);
if(d==1) k-=o->ch[0]->s+1;
if(d!=-1) {
Node* p=o->ch[d];
p->pushdown();
int d2=p->cmp(k),k2=d2==0? k:k-p->ch[d]->s-1;
if(d2!=-1) {
splay(p->ch[d2],k2);
if(d==d2) rotate(o,d^1); else rotate(o->ch[d],d);
}
rotate(o,d^1);
}
}
Node* merge(Node* left,Node* right)
{
splay(left,left->s);
left->ch[1]=right,left->maintain();
return left;
}
void split(Node* o,int k,Node*&left,Node*&right)
{
splay(o,k);
left=o,right=left->ch[1],left->ch[1]=NULL;
left->maintain();
}
Node* build(int l,int r)
{
if(r<l) return null;
int mid=l+r>>1;
G->s=1;
G->ch[0]=build(l,mid-1);
G->ch[1]=build(mid+1,r);
G->maintain();
return G++;
}

主席树:

//主席树
struct Tnode
{
Tnode *ls,*rs;
int sum;
} *T[N*50],mempool[N*50],*G=mempool; Tnode* Nw(Tnode* l,Tnode* r,int x)
{
G->ls=l,G->rs=r,G->sum=x;
return G++;
}
Tnode* build(Tnode* p,int l,int r,int pos)
{
if(l==r)
return Nw(T[0],T[0],p->sum+1);
else {
int mid=l+r>>1;
if(pos<=mid) return Nw(build(p->ls,l,mid,pos),p->rs,p->sum+1);
else return Nw(p->ls,build(p->rs,mid+1,r,pos),p->sum+1);
}
}
int query(Tnode* x,int l,int r,int pos)
{
if(l==r) return x->sum;
else {
int mid=l+r>>1;
if(pos<=mid) return query(x->ls,l,mid,pos);
else return query(x->rs,mid+1,r,pos);
}
}

Link-Cut-Tree

//Link-Cut-Tree
namespace LCT
{ struct Node {
Node *ch[2],*fa;
int rev;
//others v
Node() {};
Node(int x) ;
void reverse() {
swap(ch[0],ch[1]);
rev^=1;
}
void up_push() {
if(fa->ch[0]==this||fa->ch[1]==this)
fa->up_push();
if(rev) {
ch[0]->reverse();
ch[1]->reverse();
rev=0;
}
}
void maintain() { }
} T[N<<1],*null=&T[0];
Node::Node(int x) {
ch[0]=ch[1]=fa=null;
rev=0; //v=x;
}
void rot(Node* o,int d) {
Node* p=o->fa;
p->ch[d]=o->ch[d^1];
o->ch[d^1]->fa=p;
o->ch[d^1]=p;
o->fa=p->fa;
if(p==p->fa->ch[0])
p->fa->ch[0]=o;
else if(p==p->fa->ch[1])
p->fa->ch[1]=o;
p->fa=o;
p->maintain();
}
void splay(Node* o) {
o->up_push();
Node *nf,*nff;
while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
nf=o->fa,nff=nf->fa;
if(o==nf->ch[0]) {
if(nf==nff->ch[0]) rot(nf,0);
rot(o,0);
} else {
if(nf==nff->ch[1]) rot(nf,1);
rot(o,1);
}
}
o->maintain();
}
void Access(Node* o) {
Node *son=null;
while(o!=null) {
splay(o);
o->ch[1]=son;
o->maintain();
son=o; o=o->fa;
}
}
void evert(Node* o) {
Access(o);
splay(o);
o->reverse();
}
void Link(Node* u,Node* v) {
evert(u);
u->fa=v;
}
void Cut(Node* u,Node* v) {
evert(u);
Access(v),splay(v);
v->ch[0]=u->fa=null;
v->maintain();
}
Node* find(Node* o) {
while(o->fa!=null) o=o->fa;
return o;
} }
using namespace LCT ;

2-SAT:

//2-sat
struct TwoSAT {
int n;
vector<int> g[N<<1];
int st[N<<1],mark[N<<1],top; bool dfs(int x) {
if(mark[x^1]) return 0;
if(mark[x]) return 1;
mark[x]=1;
st[++top]=x;
for(int i=0;i<g[x].size();i++)
if(!dfs(g[x][i])) return 0;
return 1;
}
void init(int n) {
this->n=n;
for(int i=0;i<2*n;i++) g[i].clear();
memset(mark,0,sizeof(mark));
}
void addc(int x,int xval,int y,int yval) {
x=x*2+xval;
y=y*2+yval;
g[x^1].push_back(y);
g[y^1].push_back(x);
}
bool solve() {
for(int i=0;i<2*n;i+=2) {
if(!mark[i]&&!mark[i+1]) {
top=0;
if(!dfs(i)) {
while(top) mark[st[top--]]=0;
if(!dfs(i+1)) return 0;
}
}
}
return 1;
} } s;

  

有向图的强联通分量:

//tarjan求SCC
struct Edge {
int v,nxt;
}e[M];
int en=1,front[N];
void adde(int u,int v)
{
e[++en]=(Edge){v,front[u]}; front[u]=en;
} int n,top,dfn;
int st[N],sccno[N],scc_cnt,pre[N],lowlink[N]; void tarjan(int u)
{
pre[u]=lowlink[u]=++dfn;
st[++top]=u;
trav(u,i) {
int v=e[i].v;
if(!pre[v]) {
tarjan(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
} else
if(!sccno[v])
lowlink[u]=min(lowlink[u],pre[v]);
}
if(lowlink[u]==pre[u]) {
scc_cnt++;
for(;;) {
int x=st[top--];
sccno[x]=scc_cnt;
if(x==u) break;
}
}
}

无向图的边的双连通分量:

//BCC
struct Edge {
int u,v,nxt;
}e[M];
int en=1,front[N];
void adde(int u,int v)
{
e[++en]=(Edge){u,v,front[u]}; front[u]=en;
} Edge st[N];
vector<int> bcc[N];
int pre[N],iscut[N],bccno[N],top,dfn,bcc_cnt; int dfs(int u,int fa)
{
int lowu=pre[u]=++dfn;
int child=0;
trav(u,i) {
int v=e[i].v;
Edge E=e[i];
if(!pre[v]) {
st[++top]=E;
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u]) {
iscut[u]=1;
bcc_cnt++;
for(;;) {
Edge x=st[top--];
if(bccno[x.u]!=bcc_cnt) {
bccno[x.u]=bcc_cnt;
bcc[bcc_cnt].push_back(x.u);
}
if(bccno[x.v]!=bcc_cnt) {
bccno[x.v]=bcc_cnt;
bcc[bcc_cnt].push_back(x.v);
}
if(x.u==u&&x.v==v) break;
}
}
} else
if(pre[v]<pre[u] && v!=fa) {
st[++top]=E;
lowu=min(lowu,pre[v]);
}
}
if(fa<0&&child==1) iscut[u]=0;
return lowu;
}

  

最短路:

//spfa

struct Edge {
int v,w,nxt;
}e[M];
int en=1,front[N];
void adde(int u,int v,int w)
{
e[++en]=(Edge){v,w,front[u]}; front[u]=en;
} queue<int> q;
int inq[N],dis[N];
void spfa(int s)
{
dis[s]=0; inq[s]=1;
q.push(s);
while(!q.empty()) {
int u=q.front(); q.pop();
inq[u]=0;
trav(u,i) {
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w;
if(!inq[v]) {
inq[v]=1;
q.push(v);
}
}
}
}
} //dijkstra struct Node {
int id,dis;
bool operator < (const Node& rhs) const
{
return dis>rhs.dis;
}
}; priority_queue<Node> q;
int n,m,s;
int vis[N],dis[N]; void dijkstra(int s)
{
FOR(i,1,n) dis[i]=inf;
dis[s]=0; q.push((Node){s,0});
while(!q.empty()) {
int u=q.top().id;
q.pop();
if(vis[u]) continue;
vis[u]=1;
trav(u,i) {
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w;
q.push((Node){v,dis[v]});
}
}
}
}

  

  

最小生成树:

//Kruskal 

int fa[N];
int find(int u)
{
if(!fa[u] || u==fa[u]) return fa[u]=u;
return fa[u]=find(fa[u]);
} struct Edge {
int u,v,w;
bool operator < (const Edge& rhs) const
{
return w<rhs.w;
}
}e[M];
int tot; void Kruskal()
{
sort(e+1,e+tot+1);
for(int i=1;i<=tot;i++) {
int u=e[i].u,v=e[i].v;
int x=find(u),y=find(v);
if(x!=y) {
fa[x]=y;
//加入树边(u,v)
}
}
}

  

最大流:

//Dinic算法求最大流
struct Edge {
int u,v,cap,flow;
};
struct Dinic {
int d[N],cur[N],vis[N];
vector<Edge> es;
vector<int> g[N];
queue<int> q; void AddEdge (int u,int v,int w) {
es.push_back((Edge){u,v,w,0});
es.push_back((Edge){v,u,0,0});
int m=es.size();
g[u].push_back(m-2);
g[v].push_back(m-1);
}
bool bfs(int s,int t) {
memset(vis,0,sizeof(vis));
d[s]=0; vis[s]=1;
q.push(s);
while(!q.empty()) {
int u=q.front(); q.pop();
FOR(i,0,(int)g[u].size()-1) {
Edge& e=es[g[u][i]];
int v=e.v;
if(e.cap>e.flow&&!vis[v]) {
vis[v]=1;
d[v]=d[u]+1;
q.push(v);
}
}
}
return vis[t];
}
int dfs(int u,int a,int t) {
if(u==t||a==0) return a;
int flow=0,f;
for(int& i=cur[u];i<g[u].size();i++) {
Edge& e=es[g[u][i]];
int v=e.v;
if(d[v]==d[u]+1&&(f=dfs(v,min(a,e.cap-e.flow),t))>0) {
e.flow+=f;
es[g[u][i]^1].flow-=f;
flow+=f,a-=f;
if(!a) break;
}
}
return flow;
}
int maxflow(int s,int t) {
int flow=0;
while(bfs(s,t)) {
memset(cur,0,sizeof(cur));
flow+=dfs(s,inf,t);
}
return flow;
}
} dc;

  

最小费用最大流:

/最短路算法求最小费用最大流
struct Edge {
int u,v,cap,flow,cost;
Edge(int _,int __,int ___,int ____,int _____)
{ u=_,v=__,cap=___,flow=____,cost=_____; }
}; struct MCMF {
int n,m,s,t;
int d[N],p[N],a[N],inq[N];
vector<Edge> es;
vector<int> g[N];
queue<int> q;
void init(int n) {
this->n=n;
es.clear();
for(int i=0;i<=n;i++) g[i].clear();
}
void AddEdge(int u,int v,int w,int c) {
es.push_back(Edge(u,v,w,0,c));
es.push_back(Edge(v,u,0,0,-c));
int m=es.size();
g[u].push_back(m-2);
g[v].push_back(m-1);
}
bool spfa(int s,int t,ll& flow,ll& cost) {
memset(inq,0,sizeof(inq));
for(int i=0;i<=n;i++) d[i]=inf;
inq[s]=1; d[s]=p[s]=0; a[s]=inf;
q.push(s);
while(!q.empty()) {
int u=q.front(); q.pop();
inq[u]=0;
for(int i=0;i<g[u].size();i++) {
Edge& e=es[g[u][i]];
int v=e.v;
if(d[v]>d[u]+e.cost && e.cap>e.flow) {
d[v]=d[u]+e.cost;
a[v]=min(a[u],e.cap-e.flow);
p[v]=g[u][i];
if(!inq[v])
inq[v]=1 , q.push(v);
}
}
}
if(d[t]==inf) return 0;
flow+=a[t],cost+=a[t]*d[t];
for(int x=t;x!=s;x=es[p[x]].u) {
es[p[x]].flow+=a[t];
es[p[x]^1].flow-=a[t];
}
return 1;
}
void mcmf(int s,int t,ll& cost,ll& flow) {
flow=cost=0;
while(spfa(s,t,cost,flow)) ;
}
} mc;

 

KM算法:

//KM算法求二分图的最佳完美匹配
struct KM {
int slack[N],res[N];
int l[N],r[N],lx[N],rx[N],g[N][N]; void clear(int n) {
for(int i=1;i<=n;i++) {
res[i]=0;
for(int j=1;j<=n;j++) g[i][j]=-1;
}
}
bool find(int x,int n) {
lx[x]=1;
for(int i=1;i<=n;i++)
if(!rx[i]&&g[x][i]!=-1) {
int tmp=g[x][i]-l[x]-r[i];
if(!tmp) {
rx[i]=1;
if(!res[i]||find(res[i],n)) {
res[i]=x;
return 1;
}
} else
slack[i]=min(slack[i],tmp);
}
return 0;
}
int solve(int n) {
if(!n) return 0;
for(int i=1;i<=n;i++) r[i]=0;
for(int i=1;i<=n;i++) {
l[i]=INF;
for(int j=1;j<=n;j++) if(g[i][j]!=-1)
l[i]=min(l[i],g[i][j]);
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) slack[j]=INF;
for(;;) {
for(int j=1;j<=n;j++) lx[j]=rx[j]=0;
if(find(i,n)) break;
int mini=INF;
for(int i=1;i<=n;i++) if(!rx[i])
mini=min(mini,slack[i]);
for(int i=1;i<=n;i++) {
if(lx[i]) l[i]+=mini;
if(rx[i]) r[i]-=mini;
else slack[i]-=mini;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
ans+=l[i]+r[i];
return ans;
}
} km;

  

 

LCA:

//倍增法求LCA
//倍增法可以在线构造 比较灵活
struct Edge {
int v,nxt;
}e[M];
int en=1,front[N];
void adde(int u,int v)
{
e[++en]=(Edge){v,front[u]}; front[u]=en;
} int fa[N][D],dep[N]; void dfs(int u)
{
for(int i=1;i<D;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
trav(u,i) {
int v=e[i].v;
if(v!=fa[u][0]) {
fa[v][0]=u;
dep[v]=dep[u]+1;
dfs(v);
}
}
}
int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
int t=dep[u]-dep[v];
for(int i=0;i<D;i++)
if(t&(1<<i)) u=fa[u][i];
if(u==v) return u;
for(int i=D-1;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
} //树链剖分求LCA
//比较快
struct Edge {
int v,nxt;
}e[M];
int en=1,front[N];
void adde(int u,int v)
{
e[++en]=(Edge){v,front[u]}; front[u]=en;
} int fa[N],top[N],siz[N],dep[N],son[N];
void dfs1(int u)
{
siz[u]=1; son[u]=0;
trav(u,i) {
int v=e[i].v;
if(v!=fa[u]) {
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
trav(u,i)
if(e[i].v!=fa[u]&&e[i].v!=son[u])
dfs2(e[i].v,e[i].v);
}
int lca(int u,int v)
{
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]? u:v;
}

  

树链剖分:

//树链剖分
struct Edge {
int v,nxt;
}e[M];
int en=1,front[N];
void adde(int u,int v)
{
e[++en]=(Edge){v,front[u]}; front[u]=en;
} int fa[N],top[N],siz[N],dep[N],son[N],bl[N],dfn;
void dfs1(int u)
{
siz[u]=1; son[u]=0;
trav(u,i) {
int v=e[i].v;
if(v!=fa[u]) {
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int tp)
{
top[u]=tp; bl[u]=++dfn;
if(son[u]) dfs2(son[u],tp);
trav(u,i)
if(e[i].v!=fa[u]&&e[i].v!=son[u])
dfs2(e[i].v,e[i].v);
}
//以合适的数据结构T维护重链
int ans;
int query(int u,int v)
{
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans<-query(T,bl[top[u]],bl[u]);
u=fa[top[u]];
}
if(u==v) return ;
if(dep[u]>dep[v]) swap(u,v);
ans<-query(T,bl[u],bl[v]);
<-ans
}
//类似-查询树上任意两节点的方法
void modify() {}

  

点分治:

//点分治
struct Edge {
int v,nxt;
}e[M];
int en=1,front[N];
void adde(int u,int v)
{
e[++en]=(Edge){v,front[u]}; front[u]=en;
} int rt,n,size,vis[N],siz[N],f[N],dep[N]; void get_root(int u,int fa)
{
siz[u]=1; f[u]=0;
trav(u,i) {
int v=e[i].v;
if(v!=fa) {
get_root(v,u);
siz[u]+=siz[v];
if(siz[v]>f[u]) f[u]=siz[v];
}
}
f[u]=max(f[u],size-siz[u]);
if(f[u]<f[rt]) rt=u;
}
void solve(int u)
{
vis[u]=1;
//计算经过根u的信息
trav(u,i) if(!vis[e[i].v])
{
//统计当前子树信息
//与前i-1个子树信息结合计算贡献
//将当前子树信息加入前i-1个子树信息
}
trav(u,i) if(!vis[e[i].v]) {
int v=e[i].v;
size=siz[v]; rt=0;
get_root(v,-1);
solve(rt);
}
}
int main()
{
//blabla
size=f[0]=n;
rt=0; get_root(rt,-1);
solve(rt);
}

  

字符串

KMP:

//KMP算法
int f[N]; char s[N];
void get_fail()
{
int j=0;
int n=strlen(s+1);
for(int i=2;i<=n;i++) {
while(j&&s[j+1]!=s[i]) j=f[j];
if(s[j+1]==s[i]) j++;
f[i]=j;
}
}

  

AC自动机:

//AC自动机
struct AC_auto {
int sz,ch[N][26],f[N],val[N];
AC_auto() {
sz=1;
memset(ch,0,sizeof(ch));
}
void insert(char* s) {
int u=0;
for(int i=0;s[i];i++) {
int c=s[i]-'a';
if(!ch[u][c]) ch[u][c]=++sz;
u=ch[u][c];
}
val[u]=1;
}
void get_fail() {
queue<int> q;
f[0]=0;
for(int c=0;c<26;c++)
if(ch[0][c]) f[ch[0][c]]=0,q.push(ch[0][c]);
while(!q.empty()) {
int qr=q.front(); q.pop();
for(int c=0;c<26;c++) {
int u=ch[qr][c];
if(!u) continue;
q.push(u);
int v=f[qr];
while(v&&!ch[v][c]) v=f[v];
if(val[ch[v][c]]) val[u]=1;
f[u]=ch[v][c];
}
}
}
};

  

  

后缀自动机:

//后缀自动机SAM
struct SAM {
int sz,last,fa[N],ch[N][26],l[N];
SAM() {
sz=0; last=++sz;
memset(l,0,sizeof(l));
memset(fa,0,sizeof(fa));
}
void Add(int c) {
int np=++sz,p=last; last=np;
l[np]=l[p]+1;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else {
int q=ch[p][c];
if(l[q]==l[p]+1) fa[np]=q;
else {
int nq=++sz; l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for(;q==ch[p][c];p=fa[p]) ch[p][c]=nq;
}
}
}
//do some other things } sam;

  

后缀数组:

//后缀数组
#define rep(a,b,c) for(int a=(b);a>=(c);a--)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
char s[N];
int c[N],t[N],t2[N],height[N],rank[N],sa[N];
void build_sa(int m,int n) {
int *x=t,*y=t2,p,k;
FOR(i,0,m-1) c[i]=0;
FOR(i,0,n-1) c[x[i]=s[i]]++;
FOR(i,0,m-1) c[i]+=c[i-1];
rep(i,n-1,0) sa[--c[x[i]]]=i; for(k=1;k<=n;k<<=1) {
p=0;
FOR(i,n-k,n-1) y[p++]=i;
FOR(i,0,n-1) if(sa[i]>=k) y[p++]=sa[i]-k; FOR(i,0,m-1) c[i]=0;
FOR(i,0,n-1) c[x[y[i]]]++;
FOR(i,0,m-1) c[i]+=c[i-1];
rep(i,n-1,0) sa[--c[x[y[i]]]]=y[i]; swap(x,y);
p=1; x[sa[0]]=0;
FOR(i,1,n-1)
x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]? p-1:p++;
if(p>=n) break;
m=p;
}
}
void get_height(int n)
{
FOR(i,0,n-1) rank[sa[i]]=i;
int k=0;
FOR(i,0,n-1) {
if(k) k--;
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}

  

Manacher:

//Manacher算法
char s[N],a[N];
int p[N];
void Add(int l,int r)
{
l=l/2,r=r/2-1;
if(l>r) return ;
//q[++tot]=(Seg){l,r};
//[l,r]为一个极大回文串
}
void Manacher()
{
int n=strlen(s+1);
int m=n*2+1;
for(int i=1;i<=n;i++) {
a[i<<1]=s[i];
a[i<<1|1]='#';
}
a[0]='+',a[1]='#',a[m+1]='-';
int mx=0,id;
for(int i=1;i<=m;i++) {
if(mx>i) p[i]=min(mx-i,p[id*2-i]);
else p[i]=1;
while(a[i-p[i]]==a[i+p[i]]) p[i]++;
Add(i-p[i],i+p[i]);
if(p[i]+i>mx) mx=i+p[i],id=i;
}
}

  

计算几何

计算几何基础知识:

//计算几何基础

const double eps = 1e-10;
int dcmp(double x) {
if(fabs(x)<eps) return 0; else return x<0? -1:1;
} struct Pt {
double x,y;
Pt(double x=0,double y=0):x(x),y(y) {}
};
typedef Pt vec; vec operator - (Pt A,Pt B) { return vec(A.x-B.x,A.y-B.y); }
vec operator + (vec A,vec B) { return vec(A.x+B.x,A.y+B.y); }
vec operator * (vec A,double p) { return vec(A.x*p , A.y*p); }
bool operator < (const Pt& a,const Pt& b) {
return a.x<b.x || (a.x==b.x && a.y<b.y);
}
bool operator == (const Pt& a,const Pt& b) {
return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
} double cross(vec A,vec B) { return A.x*B.y-A.y*B.x; }
double Dot(vec A,vec B) { return A.x*B.x+A.y*B.y; }
double Len(vec A) { return sqrt(Dot(A,A)); }
double Angle(vec A,vec B) { return acos(Dot(A,B)/Len(A)/Len(B)); } //逆时针旋转rad角度
vec rotate(vec A,double rad) {
return vec(A.x*cos(rad)-A.y*sin(rad) , A.x*sin(rad)+A.y*cos(rad));
}
//法向量 左转90度 长度归1
vec Normal(vec A)
{
double L=Len(A);
return vec(-A.y/L,A.x/L);
}
//判断点在线段上
bool OnSeg(Pt P,Pt a1,Pt a2) {
return dcmp(cross(a1-P,a2-P))==0 && dcmp(Dot(a1-P,a2-P))<0;
}
//直线交点
Pt LineIntersection(Pt P,vec v,Pt Q,vec w) {
vec u=P-Q;
double t=cross(w,u)/cross(v,w);
return P+v*t;
}
double DistoLine(Pt P,Pt A,Pt B) {
vec v1=B-A,v2=P-A;
return fabs(cross(v1,v2))/Len(v1);
}
//线段不含端点 判断相交
bool SegIntersection(Pt a1,Pt a2,Pt b1,Pt b2) {
double c1=cross(a2-a1,b1-a1) , c2=cross(a2-a1,b2-a1) ,
c3=cross(b2-b1,a1-b1) , c4=cross(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
// b1 b2在线段a1a2的两侧 a1 a2在线段b1b2的两侧 规范相交
}
//线段含端点 判断线段严格相交
bool SegInter(Pt s1, Pt e1, Pt s2, Pt e2) {
if( min(s1.x, e1.x) <= max(s2.x, e2.x) &&
min(s1.y, e1.y) <= max(s2.y, e2.y) &&
min(s2.x, e2.x) <= max(s1.x, e1.x) &&
min(s2.y, e2.y) <= max(s1.y, e1.y) &&
cross(e1-s1,s2-s1) * cross(e1-s1,e2-s1) <= 0 &&
cross(e2-s2,s1-s2) * cross(e2-s2,e1-s2) <= 0
) return true;
return false;
}
//点到线段的距离
double DistoSeg(Pt P,Pt A,Pt B) {
if(A==B) return Len(P-A);
vec v1=B-A , v2=P-A , v3=P-B;
if(dcmp(Dot(v1,v2))<0) return Len(v2);
else if(dcmp(Dot(v1,v3))>0) return Len(v3);
else return fabs(cross(v1,v2))/Len(v1);
}
//多边形面积
double PolygonArea(Pt* p,int n)
{
double S=0;
for(int i=1;i<n-1;i++)
S+=cross(p[i]-p[0],p[i+1]-p[0]);
return S/2;
}

  

凸包:

//凸包
const int N = 400000+10;
const double PI = acos(-1.0);
const double eps = 1e-12; int dcmp(double x) {
if(fabs(x)<eps) return 0; else return x<0? -1:1;
} struct Pt {
double x,y;
Pt(double x=0,double y=0) :x(x),y(y) {};
};
typedef Pt vec; vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); }
vec operator + (vec a,vec b) { return vec(a.x+b.x,a.y+b.y); }
bool operator == (Pt a,Pt b) {
return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
bool operator < (const Pt& a,const Pt& b) {
return a.x<b.x || (a.x==b.x && a.y<b.y);
} vec rotate(vec a,double x) {
return vec(a.x*cos(x)-a.y*sin(x),a.x*sin(x)+a.y*cos(x));
}
double cross(vec a,vec b) { return a.x*b.y-a.y*b.x; }
double dist(Pt a,Pt b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
} vector<Pt> ConvexHull(vector<Pt> p) {
sort(p.begin(),p.end());
p.erase(unique(p.begin(),p.end()),p.end());
int n=p.size() , m=0;
vector<Pt> ch(n+1);
for(int i=0;i<n;i++) {
while(m>1 && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--) {
while(m>k && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
ch.resize(m); return ch;
}

  

半平面交:

//半平面交

const int N =  305;
const double bond = 100001;
const double eps = 1e-10; struct Pt {
double x,y;
Pt (double x=0,double y=0):x(x),y(y){}
};
typedef Pt vec; vec operator + (Pt a,Pt b) { return vec(a.x+b.x,a.y+b.y); }
vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); }
vec operator * (Pt a,double p) { return vec(a.x*p,a.y*p); } double cross(Pt a,Pt b) { return a.x*b.y-a.y*b.x; } struct Line {
Pt p; vec v; double ang;
Line () {}
Line (Pt p,vec v) :p(p),v(v){ ang=atan2(v.y,v.x); }
bool operator < (const Line& rhs) const {
return ang<rhs.ang;
}
}; bool onleft(Line L,Pt p) { return cross(L.v,p-L.p)>0; }
Pt LineInter(Line a,Line b)
{
vec u=a.p-b.p;
double t=cross(b.v,u)/cross(a.v,b.v);
return a.p+a.v*t;
}
vector<Pt> HPI(vector<Line> L)
{
int n=L.size();
sort(L.begin(),L.end());
int f,r;
vector<Pt> p(n) , ans;
vector<Line> q(n);
q[f=r=0]=L[0];
for(int i=1;i<n;i++) {
while(f<r&&!onleft(L[i],p[r-1])) r--;
while(f<r&&!onleft(L[i],p[f])) f++;
q[++r]=L[i];
if(fabs(cross(q[r].v,q[r-1].v))<eps) {
r--;
if(onleft(q[r],L[i].p)) q[r]=L[i];
}
if(f<r) p[r-1]=LineInter(q[r-1],q[r]);
}
while(f<r&&!onleft(q[f],p[r-1])) r--;
if(r-f<=1) return ans;
p[r]=LineInter(q[r],q[f]);
for(int i=f;i<=r;i++) ans.push_back(p[i]);
return ans;
}

  

[OI]省选前模板整理的更多相关文章

  1. SDOI2019 省选前模板整理

    目录 计算几何✔ DP 斜率优化✔ 四边形不等式✔ 轮廓线DP✘ 各种分治 CDQ分治✔ 点分治✔ 整体二分✔ 数据结构 线段树合并✔ 分块✔ K-D Tree LCT 可持久化Trie✔ Splay ...

  2. NOIP前模板整理

    图 最短路径 #include <queue> #define N 1000 typedef long long ll; using namespace std; int d[N], w[ ...

  3. [TaskList] 省选前板子补完计划

    省选前本子补完计划 [ ] 带权并查集 [ ] 树上莫队 - UOJ58 [WC2013]糖果公园 loj2485「CEOI2017」Chase

  4. 省选前的JOI

    RT,发现找不到题,于是又开了新坑 JOI特色:重思考,代码难度(相比NOI系列)基本没有 (省选前到处挖坑2333) JOI 2017 Final 焚风现象 差分,莫得了 (不是看到200ms就tm ...

  5. 省选前的th题

    沙茶博主终于整完了知识点并学完了早该在NOIP之前学的知识们 于是终于开始见题了,之前那个奇怪的题单的结果就是这个了 题目按沙茶博主的做题顺序排序 个人感觉(暂时)意义不大的已被自动忽略 洛谷 491 ...

  6. 字符串系列——KMP模板整理

    KMP模板整理 KMP与扩展KMP: /*vs 2017/ vs code以外编译器,去掉windows.h头文件和system("pause");*/ #include<i ...

  7. ACM算法模板整理

    史诗级ACM模板整理 基本语法 字符串函数 istream& getline (char* s, streamsize n ); istream& getline (char* s, ...

  8. 解决el-tree lazy懒加载时,连续勾选前两个子节点后第二次进入默认选中时,将父节点也勾选的问题

    在用到el-tree的懒加载和默认勾选功能时,若第一次勾选前几个连续节点,第二次进入默认勾选时,由于el-tree子节点尚未完全加载(只加载出来前几个),默认勾选已经开始(已加载出来的子节点被默认勾选 ...

  9. 【学习笔记】OI模板整理

    CSP2019前夕整理一下模板,顺便供之后使用 0. 非算法内容 0.1. 读入优化 描述: 使用getchar()实现的读入优化. 代码: inline int read() { int x=0; ...

随机推荐

  1. Alpha阶段敏捷冲刺②

    1.提供当天站立式会议照片一张 每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 购买云服务器 注册账号 界面布局初步规划 今天计划完成的工作. 界面雏 ...

  2. mysql 时间格式化参数表笔记

    DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据. 语法: DATE_FORMAT(date,format) 实例: DATE_FORMAT(NOW(),'%b %d %Y %h:% ...

  3. [转帖]InfiniBand技术和协议架构分析

    InfiniBand技术和协议架构分析 2017年06月06日 20:54:16 Hardy晗狄 阅读数:15207 标签: 云计算存储Infiniband 更多 个人分类: 存储云计算   版权声明 ...

  4. ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))

    终于讲到反演定理了,反演定理这种东西记一下公式就好了,反正我是证明不出来的~(-o ̄▽ ̄)-o 首先,著名的反演公式 我先简单的写一下o( ̄ヘ ̄*o) 比如下面这个公式 f(n) = g(1) + g ...

  5. HDU3046_Pleasant sheep and big big wolf

    给一个n*m的数字阵,1表示羊的位置,2表示狼的位置,0表示没有东西,可以通过.在每个格子的4边都可以建立围栏,有围栏的话狼是不能通过的. 现在求最少建立多少围栏能够保证狼无法接触到羊. 题目的模型很 ...

  6. jmeter发送json数据,报405、400错误解决方案

    1.405错误解决方案:添加HTTP信息头管理器(错误因数:发送格式未设置) 2.400错误解决方案:json文本格式有误(注意:换行.空格等)解决方案:对照json文本数据(错误因数:发送的json ...

  7. C#:system.collections.generic(泛型)

    1. array是一个固定长度的,如果要动态的存储的话就不行了,虽然 System.Collections.ArrayList(),是一个动态的存储的容器,但是没有对存储中的数据进行一个约束,所以非泛 ...

  8. 【CF995F】Cowmpany Cowmpensation(动态规划,拉格朗日插值)

    [CF995F]Cowmpany Cowmpensation(多项式插值) 题面 洛谷 CF 题解 我们假装结果是一个关于\(D\)的\(n\)次多项式, 那么,先\(dp\)暴力求解颜色数为\(0. ...

  9. 20165218 《网络对抗技术》Exp1 逆向及Bof基础

    Exp1 逆向及Bof基础 基础知识 1. NOP, JNE, JE, JMP, CMP汇编指令的机器码 指令 机器码 NOP NOP指令即"空指令",在x86的CPU中机器码为0 ...

  10. Nginx访问日志分析

    nginx默认的日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$sta ...