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

数学知识

数论:

//组合数
//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. CentOS7 修改 启动级别

    1. centos7 之前应该使用init 的启动脚本 不支持并行 速度比较慢, centos7 开始使用systemd 的模式 提高了开机的性能 所以之前的init 脚本修改 启动级别应该就无效了 ...

  2. Oracle 11G RAC For Windows 2008 R2部署手册(亲测,成功实施多次)

    总体规划 服务器规划 1.建议使用两台硬件配置一模一样的服务器来作为 RAC 环境的两个物理节点 2.服务器至少需要配置两块物理网卡 3.服务器规划表: 节点 主机名 本地磁盘大小 操作系统 内存大小 ...

  3. laravel中的Contracts, ServiceContainer, ServiceProvider, Facades关系

    Contracts, ServiceContainer, ServiceProvider, Facades  Contracts 合同,契约,也就是接口,定义一些规则,每个实现此接口的都要实现里面的方 ...

  4. echarts 地图 离线json包分享

    最近,项目中需要用到地图,由于项目的特殊性,只能使用内网获取数据. 然而,echarts官网上的离线地图包(http://echarts.baidu.com/download-map.html)早在一 ...

  5. POJ1430

    这个题目初看上去是一个排列组合题,而实际上……也是一个排列组合题. 题目描述是: Description The Stirling number of the second kind S(n, m) ...

  6. Js数组和字符串常用方法

    字符串: 1.concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串.  2.indexOf() – 返回字符串中一个子串第一处出现的索引.如果没有匹配项,返回 -1 .  3.ch ...

  7. 【刷题】BZOJ 3994 [SDOI2015]约数个数和

    Description 设d(x)为x的约数个数,给定N.M,求 Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T ...

  8. 文件查找 locate 和 find

    locate locate命令依赖于一个数据库文件,系统默认每天会检索一次系统中的所有文件,然后将检索到的文件记录到数据库中; 在执行查找时,可直接到数据库中查找记录,所以locate比find反馈更 ...

  9. linux中的分段和分页

    http://blog.csdn.net/hguisu/article/details/6152921 Linux 内存管理 觉得这篇文章写分段和分页机制还是挺清晰的,在此转载一下. 前一段时间看了& ...

  10. php高效遍历文件夹、高效读取文件

    /** * PHP高效遍历文件夹(大量文件不会卡死) * @param string $path 目录路径 * @param integer $level 目录深度 */ function fn_sc ...