2020CSP—S模板
仅以此篇,纪念一年左右的OI生涯,预祝大家CSP RP++
算法
二分:
while(l<r)
{
int mid = (l+r)>>1;
int ans = solve(mid);
if(ans>m)
l=mid+1;
else
r=mid;
}
离散化
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{
c[i]=lower_bound(b+1,b+1+n,a[i])-b;
}
for(int i=1;i<=n;i++)
printf("%d ",c[i]);
//a: 500 600 700 1000 50000
//c: 1 2 3 4 5
归并排序
void msort(int l,int r)
{
if(l==r) return;
int mid = (l+r)>>1;
msort(l,mid),msort(mid+1,r);
int i=l,j=mid+1,k=i;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])
b[k++]=a[i++];
else
b[k++]=a[j++];
}
while(i<=mid)
b[k++]=a[i++];
while(j<=r)
b[k++]=a[j++];
for(int p=l;p<=r;p++)
a[p]=b[p],b[p]=0;
}
深度优先搜索
void dfs(int x)
{
if(/*剪枝 边界*/)
return ;
/*处理*/
dfs(y);
/*处理*/
}
宽度优先搜索
void bfs(int s)
{
q.push(s);
vis[s]=1;
while(!q.empty())
{
int top = q.front();
q.pop();
int y = top + dx; //由top到达的下一个点
if(!vis[y]) //边界及判重
{
ans...//更新答案
q.push(y);
}
}
}
模拟退火
void SA()
{
for(double T=100000;T>=1e-15;T*=down)
{
x = ansx + rand() * T;
int now = calc(x);
int d = now-ans;
if(now < ans)
ans = now;
else if(exp(-d/T)*RAND_MAX>rand())//有一定概率接受新解
ansx = x;
}
}
数学
线性筛素数
void euler(int n)
{
for(int i=2;i<=n;i++)
{
if(!np[i])
{
prime[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
{
np[i*prime[j]]=1;
if(i%prime[j]==0)
break;
}
}
}
GCD
int gcd(int x,int y)
{
if(y==0) return x;
else return gcd(y,x%y);
}
EXGCD
int gcd(int a,int b)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int d= gcd(b,a%b);
int k=x;
x=y;
y=x-a/b*y;
return d;
}
组合数递推
//C n m
c[1][0]=c[1][1]=0;
for(int i=2;i<=n;i++)
{
c[i][0]=1;
for(int j=1;j<=n;j++)
c[i][j]=c[i-1][j]+c[i-1][j-1];
}
线性筛欧拉函数
void euler(int n)
{
for(int i=2;i<=n;i++)
{
if(!np[i])
{
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
{
np[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
phi[i*prime[j]] = phi[i] * phi[prime[j]];
}
}
}
线性求逆元
void ny(int n)
{
for(int i=1;i<=n;i++)
{
inv[i]=((mod-mod/i)*inv[mod%i])%mod;
}
}
快速幂(非递归)
int qpow(int a,int b)
{
int ret=1;
while(b)
{
if(b&1)
ret=ret*a%mod;
a=a*a%mod;
b>>=1;
}
return ret;
}
快速幂(递归版)
int qpow(int a,int b)
{
if(b==0) return 1;
if(b%2)
return qpow(a,b/2)*qpow(a,b/2)*a;
else
return qpow(a,b/2)*qpow(a,b/2);
}
图论和树论
链式前向星
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
Floyd
void Floyd(int n)
{
memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++) f[i][i]=0;
//build
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
SPFA
void spfa(int s)
{
queue<int> q;
memset(dist,0x3f,sizeof(dist));
dist[s]=0;
q.push(s);
inq[s]=1;
while(!q.empty())
{
int x = q.front();
q.pop();
inq[x]=0;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(dist[y]>dist[x]+v[i])
{
dist[y]=dist[x]+v[i];
if(!inq[y])
q.push(y),inq[y]=1;
}
}
}
}
Dijkstra堆优化
priority_queue<pair<int,int> > q;
void dij(int s)
{
memset(dist,0x3f,sizeof(dist));
memset(v,0,sizeof(v));
dist[s]=0;
q.push(make_pair(0,s));
while(!q.empty())
{
int x = q.top().second;
if(v[x])
continue;
v[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int y =to[i];
if(dist[y]>dist[x]+val[i])
{
dist[y]=dist[x]+val[i];
q.push(make_pair(-dist[y],y));
}
}
}
}
Kruskal
bool cmp(const node&a,const node &b)
{
return a.val<b.val;
}
int find(int x)
{
if(f[x]==x) return x;
else return f[x]=find(f[x]);
}
void Kruskal()
{
for(int i=1;i<=n;i++) f[i]=i;
sort(edge+1,edge+1+m,cmp);
for(int i=1;i<=m;i++)
{
int x=edge[i].l,y=edge[i].r;
int fx=find(x);
int fy=find(y);
if(fx==fy)
continue;
else
{
f[fx]=fy;
ans+=edge[i].val;
}
}
}
树链剖分
int son[maxn],dep[maxn],sz[maxn],fa[maxn];
void dfs1(int x,int f)
{
sz[x]=1;
dep[x]=dep[f]+1;
fa[x]=f;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f)
continue;
dfs1(y,x);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]])
son[x]=y;
}
}
int top[maxn],idx[maxn],num=0;
void dfs2(int x,int tp)
{
top[x]=tp;
idx[x]=++num;
if(son[x])
dfs2(son[x],tp);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y!=son[x]&&y!=fa[x])
dfs2(y,y);
}
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
拓扑排序
void topsort()
{
queue<int> q;
for(int i=1;i<=n;i++)
if(!du[i])
q.push(i);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
du[y]--;
if(!du[y])
q.push(y);
}
}
}
Tarjan
void tarjan(int x)
{
dfn[x]=low[x]=++tim;
s.push(x);
ins[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(ins[y])
{
low[x]=min(low[x],low[y]);
}
}
if(low[x]==dfn[x])
{
int cur;
do{
cur=s.top();
s.pop();
ins[cur]=0;
sd[cur]=++cnt;
}while(x!=cur);
}
}
数据结构
并查集
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
fa[fx]=fy;
}
线段树
void mark(int l,int r,int p,int v)
{
tr[p]+=(r-l+1)*v;
lazy[p]+=v;////!!!!!!
}
void pushdown(int l,int r,int p)
{
int mid = (l+r) >> 1 ;
mark(l,mid,lson,lazy[p]);
mark(mid+1,r,rson,lazy[p]);
lazy[p]=0;
}
void pushup(int p)
{
tr[p]=tr[lson]+tr[rson];
}
void update(int l,int r,int x,int y,int v,int p)
{
if(x<=l&&y>=r)
{
mark(l,r,p,v);
return ;
}
if(lazy[p])
pushdown(l,r,p);
int mid = (l+r)>>1;
if(x<=mid) update(l,mid,x,y,v,lson);
if(y>mid) update(mid+1,r,x,y,v,rson);
pushup(p);
}
int query(int l,int r,int x,int y,int p)
{
if(x<=l&&y>=r)
return tr[p];
if(lazy[p])
pushdown(l,r,p);
int ret=0;
int mid=(l+r)>>1;
if(x<=mid) ret+=query(l,mid,x,y,lson);
if(y>mid) ret+=query(mid+1,r,x,y,rson);
return ret;
}
void build(int l,int r,int p)
{
if(l==r)
{
tr[p]=val[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,lson);
build(mid+1,r,rson);
pushup(p);
}
树状数组
void update(int x,int k)
{
for(int i=x;i<=n;i+=i&-i)
{
a[i]+=k;
}
}
int getsum(int x)
{
int ret=0;
for(int i=x;i;i-=i&-i)
{
ret+=a[i];
}
return ret;
}
单调栈
for(int i=1;i<=n;i++)
{
while(top&&a[i]>=a[s[top]])
{
p[s[top]]=i;
top--;
}
s[++top]=i;
}
单调队列(滑动窗口)
for(int i=m;i<=n;i++)
{
while(l<=r&&a[i]<=a[q[r]]) r--;
while(l<=r&&i-q[l]>=m) l++;
q[++r]=i;
printf("%d ",a[q[l]]);
}