OI/XCPC 模板合集
- 极地挑战
- 2026-02-20 05:37:50
- 1663
update on 2023.10:
这篇博客的原本意义是 方便直接复制 / 快速复习,但部分原有代码存在本质错误,完全没有起到这个作用,故重构。
由于折叠代码块在某些 markdown 编辑器中不支持,现已全文取消折叠,请善用页面右侧标题 / Ctrl+F 快速跳转。
以下是本人平时的缺省源,所以下文的代码里可能存在部分 inline 缩写为 il。
#include
#define il inline
using namespace std;
il long long read()
{
long long xr=0,F=1; char cr;
while(cr=getchar(),cr<'0'||cr>'9') if(cr=='-') F=-1;
while(cr>='0'&&cr<='9')
xr=(xr<<3)+(xr<<1)+(cr^48),cr=getchar();
return xr*F;
}
输入输出优化
int 快读
il int read()
{
int xr=0,F=1; char cr;
while(cr=getchar(),cr<'0'||cr>'9') if(cr=='-') F=-1;
while(cr>='0'&&cr<='9')
xr=(xr<<3)+(xr<<1)+(cr^48),cr=getchar();
return xr*F;
}
double 快读
il double dbread()
{
double X=0,Y=1.0; int F=1; char cr=0;
while(!isdigit(cr)) {if(cr=='-') F=-1;cr=getchar();}
while(isdigit(cr)) X=X*10+(cr^48),cr=getchar();
cr=getchar();
while(isdigit(cr)) X+=(Y/=10)*(cr^48),cr=getchar();
return X*F;
}
int 快写
void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10); putchar(x%10+'0');
}
动态规划
DP 还存在什么板子吗(?
01 背包
for(int i=1;i<=m;i++)
for(int j=t;j;j--)
if(j-w[i]>=0) f[j]=max(f[j],f[j-w[i]]+c[i]);
树形背包
void dfs(int u,int fa)
{
siz[u]=1,f[u][1]=w[u];
for(auto v:e[u]) if(v^fa)
{
dfs(v,u);
for(int j=siz[u];j;j--)
for(int k=0;k<=siz[v];k++)
f[u][j+k]=max(f[u][j+k],f[u][j]+f[v][k]);
siz[u]+=siz[v];
}
}
多重背包(二进制优化)
#include
using namespace std;
const int N=1e6+5;
int n,t,c[N],w[N];
int f[N],cnt;
int main()
{
scanf("%d%d",&n,&t);
for(int i=1,W,C,m;i<=n;i++)
{
scanf("%d%d%d",&C,&W,&m);
int j;
for(j=0;(1<<(j+1))-1<=m;j++) w[++cnt]=(1< w[++cnt]=W*(m-((1< } for(int i=1;i<=cnt;i++) for(int j=t;j;j--) if(j-w[i]>=0) f[j]=max(f[j],f[j-w[i]]+c[i]); cout< return 0; } 图论 平时的习惯是图用链前树用 vector。 最短路 Floyd 循环顺序不能颠倒。 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 queue int in[N],dis[N]; il void spfa(int s) { for(int i=1;i<=n;i++) dis[i]=inf; dis[s]=0,in[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); in[u]=0,q.pop(); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; if(!in[v]) in[v]=1,q.push(v); } } } } SPFA 判负环 这里用的是最短路长度判负环,而非入队次数。注意多测清空。 int dis[N],in[N],len[N]; il bool spfa(int s) { queue for(int i=1;i<=n;i++) dis[i]=inf,in[i]=0; dis[s]=0,in[s]=1,len[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); in[u]=0,q.pop(); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(dis[v]>dis[u]+e[i].w) { len[v]=len[u]+1,dis[v]=dis[u]+e[i].w; if(len[v]>=n) return 0; if(!in[v]) in[v]=1,q.push(v); } } } return 1; } Dijkstra priority_queue void dij(int s) { dis[s]=0; q.push(pii(0,s)); while(!q.empty()) { int u=q.top().se,f=q.top().fi; q.pop(); if(f!=dis[u])continue; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to,w=e[i].w; if(dis[v]>dis[u]+w) { dis[v]=dis[u]+w; q.push(pii(dis[v],v)); } } } } 连通性相关(tarjan 系列) 强连通分量 stack void tarjan(int u) { dfn[u]=++tot;low[u]=dfn[u];q.push(u);in[u]=1; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(!dfn[v]) {tarjan(v);low[u]=min(low[u],low[v]);} else if(in[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { num++; while(!q.empty()) { if(q.top()==u) {in[u]=0,bel[u]=num,q.pop();break;} in[q.top()]=0,bel[q.top()]=num,q.pop(); } } } 割点 注意根的特判。 int dfn[N],low[N],tot; bool flag[N]; void tarjan(int u,int rt) { dfn[u]=low[u]=++tot;int qwq=0; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(!dfn[v]) { tarjan(v,rt); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]&&rt!=u) flag[u]=1; qwq++; } else low[u]=min(low[u],dfn[v]); } if(qwq>1&&u==rt) flag[u]=1; } 点双连通分量 特判孤立点。 int dfn[N],low[N],tot,num; stack vector void tarjan(int u,int fa) { dfn[u]=low[u]=++tot; q.push(u); int son=0; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(v==fa) continue; if(!dfn[v]) { son=1; tarjan(v,u),low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) { num++; while(q.top()!=u) { int x=q.top(); ans[num].push_back(q.top()),q.pop(); if(x==v) break; } ans[num].push_back(u); } } else low[u]=min(low[u],dfn[v]); } if(!fa&&!son) ans[++num].push_back(u); } 割边(桥) upd: 这个要注意是否有重边,有的话应该记录经过的上一条边而非上一个点。 void tarjan(int u,int fa) { low[u]=dfn[u]=++tot; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to;if(v==fa) continue; if(!dfn[v]) { tarjan(v,u); low[u]=min(low[u],low[v]); if(low[v]>dfn[u]) flag[(i+1)/2]=1; } else low[u]=min(low[u],dfn[v]); } } 边双连通分量 int dfn[N],low[N],tot,num; stack vector void tarjan(int u,int lst) { dfn[u]=low[u]=++tot; q.push(u); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(i==(lst^1)) continue; if(!dfn[v]) tarjan(v,i),low[u]=min(low[u],low[v]); else low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { num++; while("qwq") { int x=q.top(); q.pop(),ans[num].push_back(x); if(x==u) break; } } } 图的匹配 & 网络流 匈牙利 int f[N][N],vis[N],mat[N]; bool dfs(int u) { for(int i=1;i<=m;i++) if(!vis[i]&&f[u][i]) { vis[i]=1; if(!mat[i]||dfs(mat[i])) {mat[i]=u;return 1;} } return 0; } for(int i=1;i<=n;i++) dfs(i),memset(vis,0,sizeof(vis)); EK 最大流 int vis[N],pre[N],dis[N]; bool bfs(int s,int t) { for(int i=1;i<=n;i++) vis[i]=0,pre[i]=-1,dis[i]=inf; queue vis[s]=1; while(!q.empty()) { int u=q.front();q.pop(); if(u==t) return 1; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to,w=e[i].w; if(vis[v]||!w) continue; vis[v]=1,pre[v]=i; dis[v]=min(dis[u],w); q.push(v); } } return 0; } void upd(int s,int t) { int now=t; while(now!=s) { int i=pre[now]; e[i].w-=dis[t]; e[i^1].w+=dis[t]; now=e[i^1].to; } ans+=dis[t]; } Dinic 最大流 il void add(int u,int v,int w) { e[++cnt]={head[u],v,w};head[u]=cnt; e[++cnt]={head[v],u,0};head[v]=cnt; } int dis[N],now[N]; queue il bool bfs() { for(int i=1;i<=n;i++) dis[i]=inf,now[i]=head[i]; dis[s]=0;q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(e[i].w&&dis[v]==inf) dis[v]=dis[u]+1,q.push(v); } } return dis[t]!=inf; } int dfs(int u,int sum) { int res=0; if(u==t) return sum; for(int i=now[u];i&∑i=e[i].nxt) { now[u]=i; int v=e[i].to; if(!e[i].w||dis[v]!=dis[u]+1) continue; int k=dfs(v,min(sum,e[i].w)); e[i].w-=k,e[i^1].w+=k,sum-=k,res+=k; } return res; } EK 费用流 bool spfa() { queue for(int i=1;i<=n;i++) dis[i]=mn[i]=inf,pre[i]=-1,in[i]=0; dis[s]=0,in[s]=1;q.push(s); while(!q.empty()) { int u=q.front();q.pop();in[u]=0; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to,w=e[i].w; if(!w) continue; if(dis[v]>dis[u]+e[i].c) { dis[v]=dis[u]+e[i].c; mn[v]=min(mn[u],e[i].w); pre[v]=i; if(!in[v]) in[v]=1,q.push(v); } } } if(dis[t]==inf) return 0; else return 1; } int ans1,ans2; void upd() { int now=t; while(now!=s) { int i=pre[now]; e[i].w-=mn[t],e[i^1].w+=mn[t]; now=e[i^1].to; } ans1+=mn[t];ans2+=dis[t]*mn[t]; } Dinic 费用流(zkw 费用流) int dis[N],in[N],now[N]; queue bool spfa() { for(int i=1;i<=n;i++) dis[i]=inf,now[i]=head[i]; dis[s]=0,in[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); in[u]=0;q.pop(); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(e[i].w&&dis[v]>dis[u]+e[i].c) { dis[v]=dis[u]+e[i].c; if(!in[v]) in[v]=1,q.push(v); } } } return dis[t]!=inf; } int dfs(int u,int sum) { if(u==t) return sum; in[u]=1; int res=0; for(int i=now[u];i&∑i=e[i].nxt) { now[u]=i; int v=e[i].to; if(e[i].w&&dis[v]==dis[u]+e[i].c&&!in[v]) { int k=dfs(v,min(e[i].w,sum)); e[i].w-=k,e[i^1].w+=k,sum-=k,res+=k; } } in[u]=0;return res; } 上下界最大流 const int N=1e5+5,inf=1e9; struct edge{ int nxt,to,w; }e[N<<1]; int head[N],cnt=1; void add(int u,int v,int w) { e[++cnt]={head[u],v,w};head[u]=cnt; e[++cnt]={head[v],u,0};head[v]=cnt; } int n,m,s,t; int dis[N],now[N]; struct qaq{ int u,v,l,r; }E[N]; bool bfs(int s,int t) { queue for(int i=s;i<=t;i++) dis[i]=inf,now[i]=head[i]; dis[s]=0,q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(dis[v]!=inf||!e[i].w) continue; dis[v]=dis[u]+1,q.push(v); } } return dis[t]!=inf; } int dfs(int u,int t,int sum) { if(u==t) return sum; int res=0; for(int i=now[u];i&∑i=e[i].nxt) { int v=e[i].to; now[u]=i; if(dis[v]!=dis[u]+1||!e[i].w) continue; int k=dfs(v,t,min(e[i].w,sum)); e[i].w-=k,e[i^1].w+=k; sum-=k,res+=k; } return res; } int W[N]; int calc(int n,int m,int s,int t) { memset(head,0,sizeof(head)),cnt=1; memset(W,0,sizeof(W)); for(int i=1;i<=m;i++) { int u=E[i].u,v=E[i].v,l=E[i].l,r=E[i].r; add(u,v,r-l),W[u]-=l,W[v]+=l; } int S=0,T=n+1;int sum=0; add(t,s,inf); for(int i=1;i<=n;i++) { if(W[i]>0) add(S,i,W[i]),sum+=W[i]; else add(i,T,-W[i]); } int res=0,ans=0; while(bfs(S,T)) res+=dfs(S,T,inf); if(res!=sum) return -1; while(bfs(s,t)) ans+=dfs(s,t,inf); return ans; } 树上问题 Kruskal bool cmp(node a,node b) {return a.w int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++) { if(find(e[i].u)==find(e[i].v)) continue; ans+=e[i].w; fa[find(e[i].v)]=find(e[i].u); if(cnt==n-2) {cnt++;break;} } printf("%d",ans); return 0; } 堆优化 Prim int vis[N]; priority_queue int Prim(int s) { int ans=0; q.push(pii(0,s)); while(!q.empty()) { int w=q.top().fi,u=q.top().se;q.pop(); if(vis[u]) continue; ans=max(ans,w);vis[u]=1; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(vis[v]) continue; q.push(pii(e[i].w,v)); } } return ans; } 倍增 LCA 循环边界不要写 __lg(n),这样会把 \(\log\) 跑满,常数真的很大。 int f[21][N],dep[N]; void init(int u,int fa) { f[0][u]=fa,dep[u]=dep[fa]+1; for(int i=1;i<=__lg(dep[u]);i++) f[i][u]=f[i-1][f[i-1][u]]; for(auto v:e[u]) if(v^fa) init(v,u); } int lca(int x,int y) { if(dep[x] for(int i=__lg(dep[x]);i>=0;i--) if(dep[f[i][x]]>=dep[y]) x=f[i][x]; for(int i=__lg(dep[x]);i>=0;i--) if(f[i][x]!=f[i][y]) x=f[i][x],y=f[i][y]; return x==y?x:f[0][x]; } 树剖 LCA & k 级祖先 int dfn[N],tot,y[N],dep[N],siz[N],son[N],top[N],fa[N]; void dfs1(int u,int ff) { dep[u]=dep[ff]+1,siz[u]=1,fa[u]=ff; for(auto v:e[u]) if(v^ff) { dfs1(v,u),siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } void dfs2(int u,int tp) { dfn[u]=++tot,y[tot]=u,top[u]=tp; if(son[u]) dfs2(son[u],tp); for(auto v:e[u]) if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } il int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]] x=fa[top[x]]; } return dep[x] } il int kfa(int x,int k) { int dp=dep[x]-k; while(dep[top[x]]>dp) x=fa[top[x]]; return y[dfn[x]-(dep[x]-dp)]; } dfs 序 LCA int dfn[N],tot,st[20][N],dep[N]; il int get(int x,int y) {return dep[x] void dfs(int u,int fa) { dfn[u]=++tot,st[0][tot]=fa,dep[u]=dep[fa]+1; for(auto v:e[u]) if(v^fa) dfs(v,u); } void init() { dfs(rt,0); for(int i=1;i<=__lg(n);i++) for(int j=1;j<=n-(1<
st[i][j]=get(st[i-1][j],st[i-1][j+(1< } int lca(int x,int y) { if(x==y) return x; if((x=dfn[x])>(y=dfn[y])) swap(x,y); int len=__lg(y-x); return get(st[len][x+1],st[len][y-(1< } 树上 k 级祖先 vector int dep[N],mxdep[N],son[N],fa[N],top[N]; int f[21][N],highbit[N]; void dfs1(int u,int ff) { mxdep[u]=dep[u]=dep[ff]+1,fa[u]=ff,f[0][u]=ff; for(int i=1;i<=__lg(dep[u]);i++) f[i][u]=f[i-1][f[i-1][u]]; for(auto v:e[u]) if(v^ff) { dfs1(v,u); if(mxdep[v]>mxdep[u]) son[u]=v,mxdep[u]=mxdep[v]; } } void dfs2(int u,int tp) { top[u]=tp; if(u==tp) { for(int i=0,f=u;i<=mxdep[u]-dep[u];i++) U[u].push_back(f),f=fa[f]; for(int i=0,f=u;i<=mxdep[u]-dep[u];i++) D[u].push_back(f),f=son[f]; } if(son[u]) dfs2(son[u],tp); for(auto v:e[u]) if(v!=son[u]) dfs2(v,v); } il int kfa(int x,int k) { if(!k) return x; x=f[highbit[k]][x],k^=(1< assert(abs(k)<=mxdep[x]-dep[x]); return k>=0?U[x][k]:D[x][-k]; } 树剖维护树链 & 子树权值和 #define int long long const int N=1e5+5; int rt,mod; int n,m,a[N],y[N]; il void add(int &x,int y) {x+=y;if(x>=mod) x-=mod;} struct segtree { #define ls (now<<1) #define rs (now<<1|1) #define mid (l+r>>1) int tr[N<<2],lz[N<<2]; void build(int now,int l,int r) { if(l==r) {tr[now]=a[y[l]]%mod;return;} build(ls,l,mid),build(rs,mid+1,r); tr[now]=(tr[ls]+tr[rs])%mod; } void modify(int now,int l,int r,int ml,int mr,int k) { tr[now]+=(mr-ml+1)*k; if(l==ml&&r==mr) {add(lz[now],k);return;} if(mr<=mid) modify(ls,l,mid,ml,mr,k); else if(ml>mid) modify(rs,mid+1,r,ml,mr,k); else modify(ls,l,mid,ml,mid,k),modify(rs,mid+1,r,mid+1,mr,k); } int query(int now,int l,int r,int ml,int mr) { if(l==ml&&r==mr) return tr[now]; int res=lz[now]*(mr-ml+1)%mod; if(mr<=mid) return (res+query(ls,l,mid,ml,mr))%mod; else if(ml>mid) return (res+query(rs,mid+1,r,ml,mr))%mod; else return (res+query(ls,l,mid,ml,mid)+query(rs,mid+1,r,mid+1,mr))%mod; } }seg; vector int fa[N],dfn[N],tot,siz[N],son[N],top[N],dep[N]; void dfs1(int u,int ff) { fa[u]=ff,siz[u]=1,dep[u]=dep[ff]+1; for(auto v:e[u]) if(v^ff) { dfs1(v,u),siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } void dfs2(int u,int tp) { dfn[u]=++tot,y[tot]=u,top[u]=tp; if(son[u]) dfs2(son[u],tp); for(auto v:e[u]) if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } il void addline(int x,int y,int k) { while(top[x]!=top[y]) { if(dep[top[x]] seg.modify(1,1,n,dfn[top[x]],dfn[x],k); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); seg.modify(1,1,n,dfn[x],dfn[y],k); } il int queryline(int x,int y) { int res=0; while(top[x]!=top[y]) { if(dep[top[x]] add(res,seg.query(1,1,n,dfn[top[x]],dfn[x])); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); add(res,seg.query(1,1,n,dfn[x],dfn[y])); return res; } il void addsub(int x,int k) {seg.modify(1,1,n,dfn[x],dfn[x]+siz[x]-1,k);} il int querysub(int x) {return seg.query(1,1,n,dfn[x],dfn[x]+siz[x]-1);} prufer 序列 namespace sub1 { int fa[N],a[N],son[N]; void solve() { for(int i=1;i for(int i=1,j=1;i<=n-2;i++,j++) { while(son[j]) j++; a[i]=fa[j]; while(i<=n-2&&!(--son[a[i]])&&a[i] } int ans=0; for(int i=1;i<=n-2;i++) ans^=i*a[i]; printf("%lld\n",ans); } } namespace sub2 { int fa[N],a[N],son[N]; void solve() { for(int i=1;i<=n-2;i++) a[i]=read(),son[a[i]]++; a[n-1]=n; for(int i=1,j=1;i { while(son[j]) j++; fa[j]=a[i]; while(i } int ans=0; for(int i=1;i printf("%lld\n",ans); } } 其他 欧拉回路 stack void dfs(int u) { for(int i=head[u];i;i=head[u]) { head[u]=e[i].nxt; int v=e[i].to; dfs(v); } q.push(u); } 数学 线性代数 快速幂 int qpow(int n,int k) { int res=1; for(;k;n=n*n%mod,k>>=1) if(k&1) res=res*n%mod; return res; } 矩阵快速幂 il void add(int &x,int y) {x+=y;if(x>=mod) x-=mod;} struct matrix { int f[2][2]; matrix() {memset(f,0,sizeof(f));} void init() {f[0][0]=f[1][1]=1;} friend matrix operator *(const matrix &a,const matrix &b) { matrix res; for(int i=0;i<2;i++) for(int k=0;k<2;k++) for(int j=0;j<2;j++) add(res.f[i][j],a.f[i][k]*b.f[k][j]%mod); return res; } }; matrix qpow(matrix n,int k) { matrix res; res.init(); for(;k;n=n*n,k>>=1) if(k&1) res=res*n; return res; } 高斯消元 void gauss() { for(int j=1;j<=n;j++) { for(int i=j;i<=n;i++) if(f[i][j]) {swap(f[i],f[j]);break;} if(fabs(f[j][j]) for(int i=1;i<=n;i++) { if(i==j) continue; double K=f[i][j]/f[j][j]; for(int k=1;k<=n+1;k++) f[i][k]-=K*f[j][k]; } } for(int i=1;i<=n;i++) f[i][n+1]/=f[i][i]; } 行列式 struct matrix { int n,m,f[N][N]; matrix() {n=m=0;memset(f,0,sizeof(f));} int * operator [](const int &x) {return f[x];} }; int det(matrix f) { int res=1; for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { while(f[i][i]) { int div=f[j][i]/f[i][i]; for(int k=i;k<=n;k++) f[j][k]=(f[j][k]-1ll*f[i][k]*div%mod+mod)%mod; swap(f.f[i],f.f[j]),res*=-1; } swap(f.f[i],f.f[j]),res*=-1; } for(int i=1;i<=n;i++) res=1ll*res*f[i][i]%mod; return (res+mod)%mod; } 线性基 贪心法 int n,p[N]; il void ins(int x) { for(int i=49;i>=0;i--) if(x>>i&1) { if(!p[i]) {p[i]=x;return;} x^=p[i]; } } 如果不想写高斯消元,可以在贪心后调整,变成与高斯消元法相同的形式: for(int i=63;i>=0;i--) { if(!p[i]) continue; for(int j=63;j>i;j--) if((p[j]>>i)&1) p[j]^=p[i]; } 数论 欧拉函数 要复习 int now=m; for(int i=2;i*i<=m;i++) { if(now%i==0) { phi=phi*(i-1)/i; while(now%i==0) now/=i; } } if(now>1) phi=phi*(now-1)/now; exgcd void exgcd(int a,int b,int &x,int &y) { if(!b) {x=1,y=0;return;} exgcd(b,a%b,y,x); y-=x*(a/b); } Lucas 定理 int c(int n,int m){ if(m>n) return 0; return jc[n]*qpow(jc[m],mod-2)%mod*qpow(jc[n-m],mod-2)%mod; } int lucas(int n,int m){ if(!m) return 1; return lucas(n/mod,m/mod)*c(n%mod,m%mod)%mod; } 原根 inline bool check1(int x)//check原根存在性 { if(x==2||x==4) return 1; if(x%2==0) x/=2; if(x%2==0) return 0; //bool flag=0; for(int i=2;i*i<=x;i++) { if(x%i==0) { while(x%i==0) x/=i; return (x==1); } } return 1; } inline bool check2(int x,int n)//判定合法性 { if(__gcd(x,n)>1) return 0; int m=phi[n];tot=0; for(int i=2;i*i<=m;i++) { if(m%i==0) { fac[++tot]=i; while(m%i==0) m/=i; } } if(m>1) fac[++tot]=m; for(int i=1;i<=tot;i++) if(qpow(x,phi[n]/fac[i],n)==1) return 0; return 1; } BSGS #define int long long int p,b,n; unordered_map int qpow(int n,int k) { int res=1; for(;k;n=n*n%p,k>>=1) if(k&1) res=res*n%p; return res; } signed main() { p=read(),b=read(),n=read(); int t=sqrt(p); if(t*t
for(int i=0;i<=t;i++) mp[n*qpow(b,i)%p]=i; for(int i=1;i<=t;i++) { if(mp[qpow(b,t*i)]) { printf("%lld\n",t*i-mp[qpow(b,t*i)]); return 0; } } printf("no solution\n"); return 0; } exBSGS const int P=1e7-9; const int N=1e7+5; struct hsh{ int w,val,nxt; }e[N]; int head[N],tt; void ins(int x,int val) { for(int i=head[x%P];i;i=e[i].nxt) if(e[i].w==x) {e[i].val=val;return;} e[++tt]={x,val,head[x%P]};head[x%P]=tt; } int find(int x) { for(int i=head[x%P];i;i=e[i].nxt) if(e[i].w==x) return e[i].val; return 0; } int BSGS(int a,int n,int p,int ad) { int t=ceil(sqrt(p)),s=1; for(int i=1;i<=t;i++) s=1ll*s*a%p,ins(1ll*s*n%p,i); int qwq=s;s=ad; for(int i=0;i<=t;i++,s=1ll*s*qwq%p) { if(find(s)&&1ll*i*t-find(s)>0) { int res=1ll*i*t-find(s),ss=1;tt=0; for(int i=1;i<=t;i++) ss=1ll*ss*a%p,head[(1ll*ss*n%p)%P]=0; return res; } } s=1;tt=0; for(int i=1;i<=t;i++) s=1ll*s*a%p,head[(1ll*s*n%p)%P]=0; return -1; } int exBSGS(int a,int n,int p) { a%=p,n%=p; if(n==1||p==1) return 0; int cnt=0,ad=1; while("qwq") { int d=__gcd(a,p); if(d==1) break; if(n%d) return -1; cnt++;n/=d,p/=d; ad=(1ll*ad*a/d)%p; if(ad==n) return cnt; } int ans=BSGS(a,n,p,ad); return ans==-1?-1:ans+cnt; } signed main() { while("pap") { int a=read(),p=read(),n=read(); if(!a) return 0; int ans=exBSGS(a,n,p); if(ans==-1) printf("No Solution\n"); else printf("%d\n",ans); } return 0; } 类欧几里得 #include #define int long long using namespace std; const int mod=998244353,inv2=499122177,inv6=166374059; int T,n,a,b,c; struct node{ int f=0,g=0,h=0; }; node solve(int a,int b,int c,int n) { node d; if(!a) { d.f=(b/c)*(n+1)%mod; d.g=n*(n+1)%mod*inv2%mod*(b/c)%mod; d.h=(b/c)*(b/c)%mod*(n+1)%mod; } else if(a>=c||b>=c) { node q=solve(a%c,b%c,c,n); d.f=((n*(n+1)%mod*inv2%mod*(a/c)%mod+(n+1)*(b/c)%mod+q.f)+mod)%mod; d.g=((a/c)*n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod+(b/c)*n%mod*(n+1)%mod*inv2%mod+q.g)%mod; d.h=(2*(b/c)%mod*q.f%mod+2*(a/c)%mod*q.g%mod+(a/c)*(a/c)%mod*n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod+(b/c)*(b/c)%mod*(n+1)%mod+(a/c)*(b/c)%mod*n%mod*(n+1)%mod+q.h)%mod; } else { int m=(a*n+b)/c; node q=solve(c,c-b-1,a,m-1); d.f=(n*m%mod-q.f+mod)%mod; d.g=(((m*n%mod*(n+1)%mod-q.h-q.f)%mod)+mod)%mod*inv2%mod; d.h=((n*m%mod*(m+1)%mod-2*q.g%mod-2*q.f%mod-d.f)%mod+mod)%mod; } //cout<
return d; } signed main() { scanf("%lld",&T); while(T--) { scanf("%lld%lld%lld%lld",&n,&a,&b,&c); node ans=solve(a,b,c,n); cout< } return 0; } 筛法 Eratosthenes 筛 bool flag[N]; void Eratosthenes(int n) { for(int i=2;i<=n;i++) { if(flag[i])continue; for(int j=2;j*i<=n;j++) flag[j*i]=1; } } Euler 筛 for(int i=2;i<=n;i++) { if(!flag[i]) p[++cnt]=i; for(int j=1;j<=cnt&&i*p[j]<=n;j++) { flag[i*p[j]]=1; if(!i%p[j]) break; } } 线性筛欧拉函数 phi[1]=1; for(int i=2;i<=n;i++) { if(!flag[i]) {p[++cnt]=i;phi[i]=i-1;} for(int j=1;j<=cnt&&i*p[j]<=n;j++) { flag[i*p[j]]=1; if(!(i%p[j])) {phi[i*p[j]]=phi[i]*p[j];break;} else phi[i*p[j]]=phi[i]*(p[j]-1); } } 线性筛莫比乌斯函数 mu[1]=1; for(int i=2;i<=mx;i++) { if(!flag[i]) p[++cnt]=i,mu[i]=-1; for(int j=1;j<=cnt&&i*p[j]<=mx;j++) { flag[i*p[j]]=1; if(i%p[j]) mu[i*p[j]]=mu[i]*mu[p[j]]; else {mu[i*p[j]]=0;break;} } } 杜教筛 int getmu(int n) { if(n<=5e6) return mu[n]; else if(mpmu[n]) return mpmu[n]; int res=1; for(int l=2,r;l<=n;l=r+1) { r=min(n,n/(n/l)); res-=(r-l+1)*getmu(n/l); } return mpmu[n]=res; } int getphi(int n) { if(n<=5e6) return phi[n]; else if(mpphi[n]) return mpphi[n]; int res=(n+1)*n/2; for(int l=2,r;l<=n;l=r+1) { r=min(n,n/(n/l)); res-=(r-l+1)*getphi(n/l); } return mpphi[n]=res; } 多项式 FFT 递归实现(常数较大,慎用) void FFT(int limit,Complex a[],int op) { if(limit==1) return; Complex a1[(limit>>1)+5],a2[(limit>>1)+5]; for(int i=0;i<=limit;i+=2) a1[i>>1]=a[i],a2[i>>1]=a[i+1]; FFT(limit>>1,a1,op),FFT(limit>>1,a2,op); Complex Wn={cos(2.0*pai/limit),sin(2.0*pai/limit)*op},w={1,0}; for(int i=0;i<(limit>>1);i++,w=w*Wn) { a[i]=a1[i]+w*a2[i]; a[i+(limit>>1)]=a1[i]-w*a2[i]; } } int main() { n=read(),m=read(); for(int i=0;i<=n;i++) a[i].x=read(); for(int i=0;i<=m;i++) b[i].x=read(); int w=1;while(w<=m+n) w<<=1; FFT(w,a,1),FFT(w,b,1); for(int i=0;i<=w;i++) a[i]=a[i]*b[i]; FFT(w,a,-1); for(int i=0;i<=n+m;i++) printf("%d ",(int)(a[i].x/w+0.5)); return 0; } 迭代实现 const int N=4e6+5; const double pi=acos(-1); int n,m,limit=1; struct Complex {double x,y;}a[N],b[N]; il Complex operator +(Complex a,Complex b) {return {a.x+b.x,a.y+b.y};} il Complex operator -(Complex a,Complex b) {return {a.x-b.x,a.y-b.y};} il Complex operator *(Complex a,Complex b) {return {a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};} int to[N]; void FFT(Complex *a,int tp) { for(int i=0;i for(int len=1;len { Complex Wn={cos(pi/len),sin(pi/len)*tp}; for(int i=0;i { Complex w={1,0}; for(int j=0;j { Complex x=a[i+j],y=w*a[i+len+j]; a[i+j]=x+y,a[i+len+j]=x-y; } } } } int main() { n=read(),m=read(); for(int i=0;i<=n;i++) a[i].x=read(); for(int i=0;i<=m;i++) b[i].x=read(); int k=0; while(limit<=n+m) limit<<=1,k++; for(int i=0;i FFT(a,1),FFT(b,1); for(int i=0;i FFT(a,-1); for(int i=0;i<=n+m;i++) printf("%d ",(int)(a[i].x/limit+0.5)); return 0; } NTT #define int long long const int N=4e6+5,mod=998244353; il int qpow(int n,int k=mod-2) { int res=1; for(;k;n=n*n%mod,k>>=1) if(k&1) res=res*n%mod; return res; } int n,m,a[N],b[N],inv=qpow(3),limit=1,to[N]; il void NTT(int *a,int tp) { for(int i=0;i for(int len=1;len { int Wn=qpow(tp>0?3:inv,(mod-1)/(len<<1)); for(int i=0;i for(int j=0,w=1;j { int x=a[i+j],y=w*a[i+len+j]%mod; a[i+j]=(x+y)%mod,a[i+len+j]=(x-y+mod)%mod; } } } signed main() { n=read(),m=read(); for(int i=0;i<=n;i++) a[i]=read(); for(int i=0;i<=m;i++) b[i]=read(); int k=0; while(limit<=m+n) limit<<=1,k++; for(int i=0;i NTT(a,1),NTT(b,1); for(int i=0;i NTT(a,-1); for(int i=0;i<=n+m;i++) printf("%lld ",a[i]*qpow(limit)%mod); return 0; } FWT void Or(int *a,int tp) { for(int len=1;len<(1< for(int i=0;i<(1< for(int j=0;j } void And(int *a,int tp) { for(int len=1;len<(1< for(int i=0;i<(1< for(int j=0;j } void Xor(int *a,int tp) { for(int len=1;len<(1< for(int i=0;i<(1< for(int j=0;j { int x=a[i+j],y=a[i+j+len]; a[i+j]=(x+y)*tp%mod,a[i+j+len]=(x-y+mod)%mod*tp%mod; } } 数据结构 路径压缩并查集 int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);} il void merge(int x,int y) { if((x=find(x))==(y=find(y))) return; fa[x]=y; } 单调栈 for(int i=1;i<=n;i++) scanf("%d",&a[i]); q.push(n); for(int i=n-1;i;i--) { //cout<
if(!q.empty()) { while(!q.empty()&&a[i]>=a[q.top()]) q.pop(); if(!q.empty()) ans[i]=q.top(); } q.push(i); } for(int i=1;i<=n;i++) cout< 单调队列 求的是区间最小值,最大值同理 st=1,ed=0; for(int i=1;i<=n;i++) { while(st<=ed&&q[st]<=i-k) st++; while(st<=ed&&a[q[ed]]>a[i]) ed--; q[++ed]=i; if(i>=k) printf("%d ",a[q[st]]); } printf("\n"); ST 表 for(int i=1;i<=n;i++) a[i]=read(),st[0][i]=a[i]; for(int i=1;i<=__lg(n);i++) for(int j=1;j<=n-(1<
while(m--) { int l=read(),r=read(); int len=__lg(r-l+1); printf("%d\n",max(st[len][l],st[len][r-(1< } 树状数组 单点加区间求和的经典应用 struct BIT { int tr[N]; il void add(int x,int k) {for(;x<=n;x+=x&(-x)) tr[x]+=k;} il int query(int x) {int res=0;for(;x;x-=x&(-x)) res+=tr[x];return res;} il int ask(int l,int r) {return query(r)-query(l-1);} }tr; 区间加单点求和 struct BIT { int tr[N]; il void modify(int x,int k) {for(;x<=n;x+=x&(-x)) tr[x]+=k;} il void add(int l,int r,int k) {modify(l,k),modify(r+1,-k);} il int query(int x) {int res=0;for(;x;x-=x&(-x)) res+=tr[x];return res;} }tr; 线段树相关 线段树 区间加区间求和 int tr[N<<2],lz[N<<2]; #define ls (now<<1) #define rs (now<<1|1) #define mid (l+r>>1) il void pushup(int now) {tr[now]=tr[ls]+tr[rs];} il void pushdown(int now,int l,int r) { tr[ls]+=lz[now]*(mid-l+1),tr[rs]+=lz[now]*(r-mid); lz[ls]+=lz[now],lz[rs]+=lz[now]; lz[now]=0; } void build(int now,int l,int r) { if(l==r) {tr[now]=a[l];return;} build(ls,l,mid),build(rs,mid+1,r); pushup(now); } void modify(int now,int l,int r,int ml,int mr,int k) { if(l==ml&&r==mr) {tr[now]+=(r-l+1)*k,lz[now]+=k;return;} pushdown(now,l,r); if(mr<=mid) modify(ls,l,mid,ml,mr,k); else if(ml>mid) modify(rs,mid+1,r,ml,mr,k); else modify(ls,l,mid,ml,mid,k),modify(rs,mid+1,r,mid+1,mr,k); pushup(now); } int query(int now,int l,int r,int ml,int mr) { if(l==ml&&r==mr) return tr[now]; pushdown(now,l,r); if(mr<=mid) return query(ls,l,mid,ml,mr); else if(ml>mid) return query(rs,mid+1,r,ml,mr); else return query(ls,l,mid,ml,mid)+query(rs,mid+1,r,mid+1,mr); } 同上,但是标记永久化版 int tr[N<<2],lz[N<<2]; void build(int now,int l,int r) { if(l==r) {tr[now]=a[l];return;} build(ls,l,mid),build(rs,mid+1,r); tr[now]=tr[ls]+tr[rs]; } void modify(int now,int l,int r,int ml,int mr,int k) { tr[now]+=(mr-ml+1)*k; if(l==ml&&r==mr) {lz[now]+=k;return;} if(mr<=mid) modify(ls,l,mid,ml,mr,k); else if(ml>mid) modify(rs,mid+1,r,ml,mr,k); else modify(ls,l,mid,ml,mid,k),modify(rs,mid+1,r,mid+1,mr,k); } int query(int now,int l,int r,int ml,int mr) { if(l==ml&&r==mr) return tr[now]; int res=lz[now]*(mr-ml+1); if(mr<=mid) return res+query(ls,l,mid,ml,mr); else if(ml>mid) return res+query(rs,mid+1,r,ml,mr); else return res+query(ls,l,mid,ml,mid)+query(rs,mid+1,r,mid+1,mr); } 区间加区间乘区间求和(线段树 2) int tr[N<<2],lza[N<<2],lzm[N<<2]; #define ls (now<<1) #define rs (now<<1|1) #define mid (l+r>>1) il void add(int &x,int y) {x+=y;x%=mod;} il void pushup(int now) {tr[now]=(tr[ls]+tr[rs])%mod;} il void pushdown(int now,int l,int r) { (tr[ls]*=lzm[now])%=mod,(tr[rs]*=lzm[now])%=mod; (lzm[ls]*=lzm[now])%=mod,(lzm[rs]*=lzm[now])%=mod; (lza[ls]*=lzm[now])%=mod,(lza[rs]*=lzm[now])%=mod; lzm[now]=1; add(tr[ls],(mid-l+1)*lza[now]%mod),add(tr[rs],(r-mid)*lza[now]%mod); add(lza[ls],lza[now]),add(lza[rs],lza[now]); lza[now]=0; } il void build(int now,int l,int r) { lzm[now]=1; if(l==r) {tr[now]=a[l];return;} build(ls,l,mid),build(rs,mid+1,r); pushup(now); } void modify1(int now,int l,int r,int ml,int mr,int k) { if(l==ml&&r==mr) {(tr[now]*=k)%=mod,(lzm[now]*=k)%=mod,(lza[now]*=k)%=mod;return;} pushdown(now,l,r); if(mr<=mid) modify1(ls,l,mid,ml,mr,k); else if(ml>mid) modify1(rs,mid+1,r,ml,mr,k); else modify1(ls,l,mid,ml,mid,k),modify1(rs,mid+1,r,mid+1,mr,k); pushup(now); } void modify2(int now,int l,int r,int ml,int mr,int k) { if(l==ml&&r==mr) {add(tr[now],(r-l+1)*k%mod),add(lza[now],k);return;} pushdown(now,l,r); if(mr<=mid) modify2(ls,l,mid,ml,mr,k); else if(ml>mid) modify2(rs,mid+1,r,ml,mr,k); else modify2(ls,l,mid,ml,mid,k),modify2(rs,mid+1,r,mid+1,mr,k); pushup(now); } int query(int now,int l,int r,int ml,int mr) { if(l==ml&&r==mr) return tr[now]; pushdown(now,l,r); if(mr<=mid) return query(ls,l,mid,ml,mr); else if(ml>mid) return query(rs,mid+1,r,ml,mr); else return (query(ls,l,mid,ml,mid)+query(rs,mid+1,r,mid+1,mr))%mod; } 主席树 #include #define ls (tr[now].l) #define rs (tr[now].r) using namespace std; const int N=1e6+5; int n,m,cnt; int a[N],rt[N]; struct node{ int l,r,v; }tr[N<<5]; int add(int now) { tr[++cnt]=tr[now]; return cnt; } int build(int now,int l,int r) { now=++cnt; if(l==r) { tr[now].v=a[l]; return now; } int mid=(l+r)>>1; tr[now].l=build(ls,l,mid); tr[now].r=build(rs,mid+1,r); return now; } int modify(int now,int l,int r,int x,int k) { now=add(now); if(l==r) { tr[now].v=k; return now; } int mid=(l+r)>>1; if(x<=mid) tr[now].l=modify(ls,l,mid,x,k); else tr[now].r=modify(rs,mid+1,r,x,k); return now; } int query(int now,int l,int r,int x) { if(l==r) return tr[now].v; int mid=(l+r)>>1; if(x<=mid) return query(ls,l,mid,x); else return query(rs,mid+1,r,x); } signed main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); rt[0]=build(0,1,n); for(int i=1;i<=m;i++) { int v,op,x,k; scanf("%d%d%d",&v,&op,&x); if(op==1) { scanf("%d",&k); rt[i]=modify(rt[v],1,n,x,k); } else { cout< rt[i]=rt[v]; } } return 0; } 可持久化权值线段树(主席树 2) 求的是静态区间 \(k\) 小值。 #include using namespace std; const int N=2e5+5; int n,m,a[N],t[N],rt[N],cnt; struct node{ int l,r,w; }tr[N<<5]; int add(int now) { tr[++cnt]=tr[now]; return cnt; } int build(int now,int l,int r) { now=++cnt; if(l==r) return now; int mid=(l+r)>>1; tr[now].l=build(tr[now].l,l,mid); tr[now].r=build(tr[now].r,mid+1,r); return now; } int modify(int now,int l,int r,int x) { now=add(now); if(l==r) { tr[now].w++; return now; } tr[now].w++; int mid=(l+r)>>1; if(x<=mid) tr[now].l=modify(tr[now].l,l,mid,x); else tr[now].r=modify(tr[now].r,mid+1,r,x); return now; } int query(int vl,int vr,int l,int r,int x) { if(l==r) return l; int mid=(l+r)>>1; int k=tr[tr[vr].l].w-tr[tr[vl].l].w; if(k>=x) return query(tr[vl].l,tr[vr].l,l,mid,x); else return query(tr[vl].r,tr[vr].r,mid+1,r,x-k); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) {scanf("%d",&a[i]);t[i]=a[i];} sort(t+1,t+n+1); int ll=unique(t+1,t+n+1)-t-1; rt[0]=build(0,1,ll); for(int i=1;i<=n;i++) { a[i]=lower_bound(t+1,t+ll+1,a[i])-t; rt[i]=modify(rt[i-1],1,ll,a[i]); } for(int i=1;i<=m;i++) { int l,r,k; scanf("%d%d%d",&l,&r,&k); cout< } return 0; } 线段树合并 #include using namespace std; const int N=5e6+5; int x[N],y[N],z[N]; int n,m,head[N],cnt,mx,rt[N],tot,ans[N]; int sum[N],dep[N],fa[N],son[N],top[N]; struct node{ int nxt,to; }e[N]; struct node1{ int tim,mx,l,r; }tr[N]; void add(int u,int v){ e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; } void dfs1(int x,int f) { dep[x]=dep[f]+1;fa[x]=f;sum[x]=1; for(int i=head[x];i;i=e[i].nxt) { int v=e[i].to; if(v==f) continue; dfs1(v,x); if(sum[v]>sum[son[x]]) son[x]=v; sum[x]+=sum[v]; } } void dfs2(int x) { if(son[fa[x]]==x) top[x]=top[fa[x]]; else top[x]=x; for(int i=head[x];i;i=e[i].nxt) { int v=e[i].to; if(v==fa[x]) continue; dfs2(v); } } int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]] x=fa[top[x]]; } if(dep[x] else return y; } int modify(int now,int l,int r,int x,int k) { if(!now) now=++tot; if(l==r) { tr[now].tim+=k; tr[now].mx=x; //cout<<"qwq "< return now; } int mid=(l+r)>>1; if(x<=mid) tr[now].l=modify(tr[now].l,l,mid,x,k); else tr[now].r=modify(tr[now].r,mid+1,r,x,k); if(tr[tr[now].l].tim>=tr[tr[now].r].tim) {tr[now].tim=tr[tr[now].l].tim;tr[now].mx=tr[tr[now].l].mx;} else {tr[now].tim=tr[tr[now].r].tim;tr[now].mx=tr[tr[now].r].mx;} return now; } int merge(int a,int b,int l,int r) { if((!a)) return b;if((!b)) return a; int mid=(l+r)>>1; if(l==r) { tr[a].tim+=tr[b].tim;tr[a].mx=l; return a; } tr[a].l=merge(tr[a].l,tr[b].l,l,mid); tr[a].r=merge(tr[a].r,tr[b].r,mid+1,r); if(tr[tr[a].l].tim>=tr[tr[a].r].tim) {tr[a].tim=tr[tr[a].l].tim;tr[a].mx=tr[tr[a].l].mx;} else {tr[a].tim=tr[tr[a].r].tim;tr[a].mx=tr[tr[a].r].mx;} return a; } void dfs3(int x) { for(int i=head[x];i;i=e[i].nxt) { int v=e[i].to; if(v==fa[x]) continue; dfs3(v); rt[x]=merge(rt[x],rt[v],1,mx); } if(tr[rt[x]].tim) ans[x]=tr[rt[x]].mx; } int main() { scanf("%d%d",&n,&m); for(int i=1,u,v;i { scanf("%d%d",&u,&v); add(u,v);add(v,u); } for(int i=1;i<=m;i++) { scanf("%d%d%d",&x[i],&y[i],&z[i]); mx=max(mx,z[i]); } dfs1(1,0);dfs2(1); //for(int i=1;i<=n;i++) cout< for(int i=1;i<=m;i++) { int l=lca(x[i],y[i]); //cout< rt[x[i]]=modify(rt[x[i]],1,mx,z[i],1); rt[y[i]]=modify(rt[y[i]],1,mx,z[i],1); rt[l]=modify(rt[l],1,mx,z[i],-1); if(fa[l]) rt[fa[l]]=modify(rt[fa[l]],1,mx,z[i],-1); } dfs3(1); for(int i=1;i<=n;i++) cout< return 0; } 李超线段树 #include #define ls (now<<1) #define rs (now<<1|1) using namespace std; typedef double db; const int N=1e5+5; const db eps=1e-9; int n,lastans=0,cnt; int tr[N<<2],ans; db maxn; struct node {db k,b;}a[N]; db gety(int id,db x){ if(id==0) return 0; return a[id].k*x+a[id].b; } int readx(int x) {return (x+lastans-1)%39989+1;} int ready(int x) {return (x+lastans-1)%1000000000+1;} void modify(int now,int l,int r,int ml,int mr,int id) { int mid=(l+r)>>1; if(l==ml&&r==mr) { int trw=tr[now]; if(gety(id,mid)>gety(tr[now],mid)) tr[now]=id; if(gety(id,l)-gety(trw,l)>-eps&&gety(id,r)-gety(trw,r)>-eps) return; else if(gety(id,l)-gety(trw,l) if(gety(id,mid)>gety(trw,mid)) {modify(ls,l,mid,ml,mid,trw);modify(rs,mid+1,r,mid+1,mr,trw);} else {modify(ls,l,mid,ml,mid,id);modify(rs,mid+1,r,mid+1,mr,id);} } if(mr<=mid) modify(ls,l,mid,ml,mr,id); else if(ml>mid) modify(rs,mid+1,r,ml,mr,id); else {modify(ls,l,mid,ml,mid,id);modify(rs,mid+1,r,mid+1,mr,id);} } void query(int now,int l,int r,int x) { int mid=(l+r)>>1; if(gety(tr[now],x)>maxn||(gety(tr[now],x)==maxn&&tr[now] if(l==r) return; if(x<=mid) query(ls,l,mid,x); else query(rs,mid+1,r,x); } int main() { scanf("%d",&n); for(int i=1,op,xa,ya,xb,yb;i<=n;i++) { scanf("%d",&op); if(op==0) { scanf("%d",&xa);xa=readx(xa); maxn=0.0,ans=0; query(1,1,40000,xa); cout< lastans=ans; } else { scanf("%d%d%d%d",&xa,&ya,&xb,&yb); xa=readx(xa);xb=readx(xb);ya=ready(ya);yb=ready(yb); if(xa>xb) {swap(xa,xb);swap(ya,yb);} db k=0.0,b=0.0; if(xa==xb) k=0.0,b=yb; else { k=(db)(yb-ya)/(db)(xb-xa); b=(db)yb-k*(db)xb; } a[++cnt]={k,b}; modify(1,1,40000,xa,xb,cnt); } } return 0; } 哈夫曼树 #include #define int long long #define pii pair #define fi first #define se second using namespace std; const int N=1e5+5; int n,k,w[N],ans; priority_queue signed main() { scanf("%lld%lld",&n,&k); for(int i=1;i<=n;i++) { scanf("%lld",&w[i]); q.push(pii(w[i],0)); } while((q.size()-1)%(k-1)) q.push(pii(0,0)); while(q.size()>1) { int sum=0,maxn=0; for(int i=1;i<=k;i++) { if(q.empty()) break; sum+=q.top().fi; maxn=max(maxn,q.top().se); q.pop(); } ans+=sum; q.push(pii(sum,maxn+1)); } cout< return 0; } 笛卡尔树 #include #define ll long long using namespace std; const int N=1e7+5; inline int read() { int xr=0;char cr; cr=getchar(); while(cr<'0'||cr>'9') cr=getchar(); while(cr>='0'&&cr<='9') xr=(xr<<3)+(xr<<1)+(cr^48),cr=getchar(); return xr; } struct node{ int l,r; }tr[N]; int n,a[N],w[N]; int q[N],st; inline void build() { for(int i=1;i<=n;i++) { int x=a[i],now=0; while(st&&a[q[st]]>x) now=q[st],st--; if(st) tr[q[st]].r=i; if(now) tr[i].l=now; q[++st]=i; } } signed main() { n=read(); for(int i=1;i<=n;i++) a[i]=read(),w[a[i]]=i; build(); ll ansl=0,ansr=0; for(int i=1;i<=n;i++) { ansl^=1ll*i*(tr[i].l+1); ansr^=1ll*i*(tr[i].r+1); //cout< } printf("%lld %lld",ansl,ansr); //cout< return 0; } 左偏树(可并堆) #define ls(x) tr[(x)].l #define rs(x) tr[(x)].r const int N=1e5+5; int n,m; struct node{ int val,id,dist; int fa,l,r; }tr[N]; int find(int x) { if(tr[x].fa==x) return x; else return tr[x].fa=find(tr[x].fa); } int merge(int x,int y) { if(!x||!y) return x+y; if(tr[x].val>tr[y].val||(tr[x].val==tr[y].val&&tr[x].id>tr[y].id)) swap(x,y); rs(x)=merge(rs(x),y); if(tr[ls(x)].dist tr[x].dist=tr[rs(x)].dist+1; return x; } bool flag[N]; int main() { n=read(),m=read(); for(int i=1;i<=n;i++) tr[i]={read(),i,1,i,0,0}; while(m--) { int op=read(),x=read(); if(op==1) { int y=read(); if(flag[x]||flag[y]) continue; x=find(x),y=find(y); if(x!=y) tr[x].fa=tr[y].fa=merge(x,y); } else { if(flag[x]) {printf("-1\n");continue;} x=find(x),flag[x]=1; printf("%d\n",tr[x].val); tr[x].fa=tr[ls(x)].fa=tr[rs(x)].fa=merge(ls(x),rs(x)); } } return 0; } 平衡树 Splay const int N=1e5+5; struct tree { int s[2],siz,fa,key; tree(){s[0]=s[1]=siz=fa=key=0;} }tr[N]; #define ls(x) tr[(x)].s[0] #define rs(x) tr[(x)].s[1] #define fa(x) tr[(x)].fa int rt,idx; il int newnode(int key) {tr[++idx].key=key,tr[idx].siz=1;return idx;} il void maintain(int x) {tr[x].siz=tr[ls(x)].siz+tr[rs(x)].siz+1;} il void clear(int x) {ls(x)=rs(x)=fa(x)=tr[x].siz=tr[x].key=0;} il bool get(int x) {return x==rs(fa(x));} il void rotate(int x) { int y=fa(x),z=fa(y); int c=get(x); if(tr[x].s[c^1]) fa(tr[x].s[c^1])=y; tr[y].s[c]=tr[x].s[c^1],tr[x].s[c^1]=y,fa(y)=x,fa(x)=z; if(z) tr[z].s[y==tr[z].s[1]]=x; //not get(y)! maintain(y),maintain(x); } il void splay(int x) { for(int f=fa(x);f=fa(x),f;rotate(x)) if(fa(f)) rotate(get(f)==get(x)?f:x); rt=x; } il void ins(int key) { int now=rt,f=0; while(now) f=now,now=tr[now].s[key>tr[now].key]; now=newnode(key),fa(now)=f,tr[f].s[key>tr[f].key]=now,splay(now); } il void del(int key) { int now=rt,p=0; while(tr[now].key!=key&&now) p=now,now=tr[now].s[key>tr[now].key]; if(!now) {splay(p);return;} splay(now); int cur=ls(now); if(!cur) {rt=rs(now),fa(rs(now))=0,clear(now);return;} while(rs(cur)) cur=rs(cur); rs(cur)=rs(now),fa(rs(now))=cur,fa(ls(now))=0,clear(now); maintain(cur),splay(cur); } il int pre(int key) { int now=rt,ans=0,p; while(now) if(p=now,tr[now].key>=key) now=ls(now); else ans=tr[now].key,now=rs(now); return splay(p),ans; } il int nxt(int key) { int now=rt,ans=0,p; while(now) if(p=now,tr[now].key<=key) now=rs(now); else ans=tr[now].key,now=ls(now); return splay(p),ans; } il int rnk(int key) { int res=1,now=rt,p; while(now) if(p=now,tr[now].key else now=ls(now); return splay(p),res; } il int kth(int rk) { int now=rt; while(now) { int sz=tr[ls(now)].siz+1; if(sz>rk) now=ls(now); else if(sz==rk) break; else rk-=sz,now=rs(now); } return splay(now),tr[now].key; } Splay 区间翻转 const int N=1e5+5,inf=2e9; struct tree { int s[2],siz,fa,key,lz; tree(){s[0]=s[1]=siz=fa=key=lz=0;} }tr[N]; #define ls(x) tr[(x)].s[0] #define rs(x) tr[(x)].s[1] #define fa(x) tr[(x)].fa int rt,idx,a[N]; il int newnode(int key) {tr[++idx].key=key,tr[idx].siz=1;return idx;} il void maintain(int x) {tr[x].siz=tr[ls(x)].siz+tr[rs(x)].siz+1;} il void clear(int x) {ls(x)=rs(x)=fa(x)=tr[x].siz=tr[x].key=0;} il bool get(int x) {return x==rs(fa(x));} il void rotate(int x) { int y=fa(x),z=fa(y); int c=get(x); if(tr[x].s[c^1]) fa(tr[x].s[c^1])=y; tr[y].s[c]=tr[x].s[c^1],tr[x].s[c^1]=y,fa(y)=x,fa(x)=z; if(z) tr[z].s[y==tr[z].s[1]]=x; //not get(y)! maintain(y),maintain(x); } il void splay(int x,int y) { for(int f=fa(x);f=fa(x),f!=y;rotate(x)) if(fa(f)!=y) rotate(get(f)==get(x)?f:x); if(!y) rt=x; } il void pushdown(int x) { if(!tr[x].lz) return; swap(ls(x),rs(x)),tr[ls(x)].lz^=1,tr[rs(x)].lz^=1; tr[x].lz=0; return; } il int find(int x) { int now=rt; x++; while(now) { pushdown(now); int sz=tr[ls(now)].siz+1; if(sz==x) break; else if(sz>x) now=ls(now); else now=rs(now),x-=sz; } return now; } il void reverse(int l,int r) { int x=find(l-1); splay(x,0); int y=find(r+1); splay(y,x); tr[ls(y)].lz^=1; } void write(int now) { pushdown(now); if(ls(now)) write(ls(now)); if(tr[now].key) printf("%d ",tr[now].key); if(rs(now)) write(rs(now)); } int n,m; il void build() { rt=newnode(0); int now=rt; for(int i=1;i<=n+1;i++) tr[now].siz=n+3-i,rs(now)=newnode(a[i]),fa(rs(now))=now,now=rs(now); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=i; build(); while(m--) { int l=read(),r=read(); reverse(l,r); } write(rt); return 0; } FHQ Treap #define ls(x) tr[(x)].l #define rs(x) tr[(x)].r const int N=1e5+5; struct node {int l,r,key,val,siz;} tr[N]; int rt,idx,x,y,z; il int add(int key) {tr[++idx]={0,0,key,rand(),1};return idx;} il void upd(int x) {tr[x].siz=tr[ls(x)].siz+tr[rs(x)].siz+1;} void split(int now,int key,int &x,int &y) { if(!now) {x=y=0;return;} if(tr[now].key<=key) x=now,split(rs(x),key,rs(x),y),upd(x); else y=now,split(ls(y),key,x,ls(y)),upd(y); } int merge(int x,int y) { if(!x||!y) return x+y; if(tr[x].val else {ls(y)=merge(x,ls(y)),upd(y);return y;} } il void ins(int key) {split(rt,key,x,y),rt=merge(merge(x,add(key)),y);} il void del(int key) { split(rt,key,y,z),split(y,key-1,x,y); y=merge(ls(y),rs(y)),rt=merge(merge(x,y),z); } il int rnk(int key) { split(rt,key-1,x,y); int res=tr[x].siz+1; rt=merge(x,y); return res; } il int kth(int rk) { int now=rt; while(now) { int sz=tr[ls(now)].siz+1; if(sz else if(sz==rk) return tr[now].key; else now=ls(now); } assert(false); return 0; } il int pre(int key) { split(rt,key-1,x,y); int now=x; while(rs(now)) now=rs(now); rt=merge(x,y); return tr[now].key; } il int nxt(int key) { split(rt,key,x,y); int now=y; while(ls(now)) now=ls(now); rt=merge(x,y); return tr[now].key; } FHQ Treap 区间翻转 #define ls(x) tr[(x)].l #define rs(x) tr[(x)].r const int N=1e5+5; struct node{int l,r,val,key,siz,lz;} tr[N]; int rt,tot,x,y,z; il void upd(int x) {tr[x].siz=tr[ls(x)].siz+tr[rs(x)].siz+1;} il void push_down(int now) { if(!tr[now].lz) return; tr[now].lz=0,swap(ls(now),rs(now)); if(ls(now)) tr[ls(now)].lz^=1; if(rs(now)) tr[rs(now)].lz^=1; } void split(int now,int rk,int &x,int &y) { if(!now) {x=y=0;return;} push_down(now); int qwq=tr[ls(now)].siz+1; if(qwq<=rk) x=now,split(rs(now),rk-qwq,rs(x),y),upd(x); else y=now,split(ls(now),rk,x,ls(y)),upd(y); } int merge(int x,int y) { push_down(x),push_down(y); if(!x||!y) return x+y; if(tr[x].val else {ls(y)=merge(x,ls(y)),upd(y);return y;} } void print(int now) { push_down(now); if(ls(now)) print(ls(now)); printf("%d ",tr[now].key); if(rs(now)) print(rs(now)); } void rev(int l,int r) { split(rt,r,y,z),split(y,l-1,x,y); tr[y].lz=1; rt=merge(merge(x,y),z); } Link Cut Tree const int N=3e5+5; struct node { int key,sum,fa,lz; int s[2]; node() {key=sum=fa=lz=s[0]=s[1]=0;} }tr[N]; #define ls(x) tr[(x)].s[0] #define rs(x) tr[(x)].s[1] #define fa(x) tr[(x)].fa il bool get(int x) {return rs(fa(x))==x;} il bool isroot(int x) {return ls(fa(x))!=x&&rs(fa(x))!=x;} il void pushup(int x) {tr[x].sum=tr[ls(x)].sum^tr[rs(x)].sum^tr[x].key;} il void pushdown(int x) { if(!tr[x].lz) return; swap(ls(x),rs(x)),tr[ls(x)].lz^=1,tr[rs(x)].lz^=1; tr[x].lz=0; } il void update(int x) { if(!isroot(x)) update(fa(x)); pushdown(x); } il void rotate(int x) { int y=fa(x),z=fa(y),c=get(x); if(!isroot(y)) tr[z].s[get(y)]=x; fa(tr[x].s[c^1])=y,tr[y].s[c]=tr[x].s[c^1],tr[x].s[c^1]=y; fa(y)=x,fa(x)=z; pushup(y),pushup(x); } il void splay(int x) { update(x); for(int f=fa(x);f=fa(x),!isroot(x);rotate(x)) if(!isroot(f)) rotate(get(f)==get(x)?f:x); } il void access(int x) {for(int p=0;x;p=x,x=fa(x)) splay(x),rs(x)=p,pushup(x);} il void makeroot(int x) {access(x),splay(x),tr[x].lz^=1;} il int find(int x) { access(x),splay(x); while(pushdown(x),ls(x)) x=ls(x); return splay(x),x; } il void link(int x,int y) {makeroot(x);if(find(y)!=x) fa(x)=y;} il void split(int x,int y) {makeroot(x),access(y),splay(y);} il void cut(int x,int y) { makeroot(x); if(find(y)==x&&fa(y)==x&&!ls(y)) fa(y)=rs(x)=0; } 字符串 Hash const int p=131; ull n,a[10005],ans; string s; ull hash(string x) { int l=x.size(); ull res=0; for(int i=0;i<=l;i++) res=res*p+x[i]; return res; } Trie struct trie{int nxt,s[26];} tr[N]; void ins(char *s) { int len=strlen(s+1),now=0; for(int i=1;i<=len;i++) { int &to=tr[now].s[s[i]-'a']; if(!to) to=++tot; now=to; } } KMP scanf("%s%s",t+1,s+1); n=strlen(t+1),m=strlen(s+1); for(int now=0,i=2;i<=m;i++) { while(now&&s[i]!=s[now+1]) now=nxt[now]; if(s[i]==s[now+1]) now++; nxt[i]=now; } for(int now=0,i=1;i<=n;i++) { while(now&&s[now+1]!=t[i]) now=nxt[now]; if(s[now+1]==t[i]) now++; if(now==m) printf("%d\n",i-m+1); } AC 自动机 (ACAM) solve 函数省略,看具体题目 char s[N]; struct trie{int nxt,s[26];} d[N]; void ins(char *s) { int len=strlen(s+1),now=0; for(int i=1;i<=len;i++) { int &to=d[now].s[s[i]-'a']; if(!to) to=++tot; now=to; } } void getfail() { queue for(int i=0;i<26;i++) if(d[0].s[i]) q.push(d[0].s[i]); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<26;i++) { if(!d[u].s[i]) d[u].s[i]=d[d[u].nxt].s[i]; else d[d[u].s[i]].nxt=d[d[u].nxt].s[i],q.push(d[u].s[i]); } } } Manacher #include using namespace std; const int N=2.2e7+5; int cnt=1,r[N],mid=1,R,maxn; char s[N],c; int main() { s[0]='~';s[1]='#'; c=getchar(); while(c<'a'||c>'z') c=getchar(); while(c>='a'&&c<='z') s[++cnt]=c,s[++cnt]='#',c=getchar(); for(int i=1;i<=cnt;i++) { if(i while(s[i-r[i]]==s[i+r[i]]) r[i]++; if(i+r[i]-1>=R) R=i+r[i]-1,mid=i; maxn=max(maxn,r[i]-1); } cout< return 0; } 回文自动机 (PAM) const int N=5e5+5; int n,tot=1; struct node { int len,fa,dep; int s[26]; }d[N]; char s[N]; il int getfail(int u,int i) { while(i-d[u].len-1<=0||s[i-d[u].len-1]!=s[i]) u=d[u].fa; return u; } int main() { scanf("%s",s+1); n=strlen(s+1); d[0].fa=1,d[1].len=-1; int now=0,lst=0; for(int i=1;i<=n;i++) { s[i]=(s[i]-'a'+lst)%26+'a'; int pos=getfail(now,i); int c=s[i]-'a'; if(!d[pos].s[c]) { d[++tot].fa=d[getfail(d[pos].fa,i)].s[c]; d[pos].s[c]=tot,d[tot].len=d[pos].len+2; d[tot].dep=d[d[tot].fa].dep+1; } now=d[pos].s[c]; printf("%d ",lst=d[now].dep); } return 0; } 后缀数组 (SA) int n,m,sa[N],rk[N],sum[N],tp[N]; int hgt[N]; void qsort() { for(int i=1;i<=m;i++) sum[i]=0; for(int i=1;i<=n;i++) sum[rk[i]]++; for(int i=1;i<=m;i++) sum[i]+=sum[i-1]; for(int i=n;i;i--) sa[sum[rk[tp[i]]]--]=tp[i]; } void SA() { for(int i=1;i<=n;i++) rk[i]=s[i],tp[i]=i; m=200,qsort(); for(int w=1,tot=0;w<=n&&tot { tot=0; for(int i=n-w+1;i<=n;i++) tp[++tot]=i; for(int i=1;i<=n;i++) if(sa[i]>w) tp[++tot]=sa[i]-w; qsort(); swap(rk,tp); tot=rk[sa[1]]=1; for(int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+w]==tp[sa[i-1]+w])?tot:++tot; } } void get_hgt() { for(int i=1,now=0;i<=n;i++) { if(now) now--; while(s[i+now]==s[sa[rk[i]-1]+now]) now++; hgt[rk[i]]=now; } } 后缀自动机 (SAM) void add(int c) { int p=lst,np=lst=++tot;f[tot]=1; d[np].len=d[p].len+1; for(;p&&!d[p].ch[c];p=d[p].fa) d[p].ch[c]=np; if(!p) d[np].fa=1; else { int q=d[p].ch[c]; if(d[q].len==d[p].len+1) d[np].fa=q; else { int nq=++tot; d[nq]=d[q];d[nq].len=d[p].len+1; d[q].fa=d[np].fa=nq; for(;p&&d[p].ch[c]==q;p=d[p].fa) d[p].ch[c]=nq; } } } 广义 SAM 离线 bfs struct trie{int fa,c,s[26];} tr[N]; int idx=1; il void ins(char *s) { int len=strlen(s+1),now=1; for(int i=1;i<=len;i++) { int &to=tr[now].s[s[i]-'a']; if(!to) to=++idx,tr[to].fa=now,tr[to].c=s[i]-'a'; now=to; } } struct SAM{int fa,len,s[26];} d[N]; int tot=1; il int insert(int c,int lst) { int p=lst,np=lst=++tot; d[np].len=d[p].len+1; for(;p&&!d[p].s[c];p=d[p].fa) d[p].s[c]=np; if(!p) {d[np].fa=1;return np;} int q=d[p].s[c]; if(d[q].len==d[p].len+1) {d[np].fa=q;return np;} int nq=++tot; d[nq]=d[q],d[nq].len=d[p].len+1; d[q].fa=d[np].fa=nq; for(;p&&d[p].s[c]==q;p=d[p].fa) d[p].s[c]=nq; return np; } int pos[N]; il void build() { queue for(int i=0;i<26;i++) if(tr[1].s[i]) q.push(tr[1].s[i]); pos[1]=1; while(!q.empty()) { int u=q.front(); q.pop(); pos[u]=insert(tr[u].c,pos[tr[u].fa]); for(int i=0;i<26;i++) if(tr[u].s[i]) q.push(tr[u].s[i]); } } 在线构造 struct SAM{int fa,len,s[26];} d[N]; int tot=1,pos[N]; il int insert(int c,int lst) { if(d[lst].s[c]&&d[d[lst].s[c]].len==d[lst].len+1) {return d[lst].s[c];} int p=lst,np=++tot,flag=0; d[np].len=d[p].len+1; for(;p&&!d[p].s[c];p=d[p].fa) d[p].s[c]=np; if(!p) {d[np].fa=1;return np;} int q=d[p].s[c]; if(d[q].len==d[p].len+1) {d[np].fa=q;return np;} if(p==lst) flag=1,np=0,tot--; int nq=++tot; d[nq]=d[q],d[nq].len=d[p].len+1; d[q].fa=d[np].fa=nq; for(;p&&d[p].s[c]==q;p=d[p].fa) d[p].s[c]=nq; return flag?nq:np; } 计算几何 扫描线 #include #define int long long #define ls (now<<1) #define rs (now<<1|1) using namespace std; const int N=3e5+5; int n; struct node{ int x,l,r,op; }a[N]; int cnt,num,b[N],lz[N<<2]; struct node1{ int mn,cnt,l; }tr[N<<2]; bool cmp(node x,node y){ return x.x } void push_down(int now) { tr[ls].mn+=lz[now];tr[rs].mn+=lz[now]; lz[ls]+=lz[now];lz[rs]+=lz[now]; lz[now]=0; } void build(int now,int l,int r) { tr[now].l=tr[now].cnt=b[r+1]-b[l]; if(l==r) return; int mid=(l+r)>>1; build(ls,l,mid);build(rs,mid+1,r); } void modify(int now,int l,int r,int ml,int mr,int op) { if(l==ml&&r==mr) tr[now].mn+=op,lz[now]+=op;return;} int mid=(l+r)>>1; push_down(now); if(mr<=mid) modify(ls,l,mid,ml,mr,op); else if(ml>mid) modify(rs,mid+1,r,ml,mr,op); else { modify(ls,l,mid,ml,mid,op); modify(rs,mid+1,r,mid+1,mr,op); } tr[now].mn=min(tr[ls].mn,tr[rs].mn); tr[now].cnt=0; if(tr[ls].mn==tr[now].mn) tr[now].cnt+=tr[ls].cnt; if(tr[rs].mn==tr[now].mn) tr[now].cnt+=tr[rs].cnt; } int query(int now,int l,int r,int ml,int mr) { if(tr[now].mn!=0) return tr[now].l; else return tr[now].l-tr[now].cnt; } signed main() { scanf("%lld",&n); for(int i=1,xa,xb,ya,yb;i<=n;i++) { scanf("%lld%lld%lld%lld",&xa,&ya,&xb,&yb); a[++cnt].x=xa,a[cnt].l=ya,a[cnt].r=yb,a[cnt].op=1; a[++cnt].x=xb,a[cnt].l=ya,a[cnt].r=yb,a[cnt].op=-1; b[++num]=ya,b[++num]=yb; } sort(b+1,b+num+1); int len=unique(b+1,b+num+1)-b-1; for(int i=1;i<=cnt;i++) { a[i].l=lower_bound(b+1,b+len+1,a[i].l)-b; a[i].r=lower_bound(b+1,b+len+1,a[i].r)-b; } sort(a+1,a+cnt+1,cmp); build(1,1,len-1); int ans=0; for(int i=1;i { modify(1,1,len-1,a[i].l,a[i].r-1,a[i].op); ans+=query(1,1,len-1,1,len-1)*(a[i+1].x-a[i].x); } cout< return 0; } 平面最近点对 #include #define int long long using namespace std; const int N=4e5+5; typedef double db; int n;db ans=1e18; struct node{ db x,y; }a[N],t[N]; bool cmpx(node c,node d) { if(c.x==d.x) return c.y else return c.x } bool cmpy(node c,node d){ return c.y } db dis(node c,node d){ return (c.x-d.x)*(c.x-d.x)+(c.y-d.y)*(c.y-d.y); } void solve(int l,int r) { if(l==r) return; int mid=(l+r)>>1; db m=a[mid].x; solve(l,mid);solve(mid+1,r); int cnt=0; for(int i=l;i<=r;i++) { if(a[i].x>=m-sqrt(ans)&&a[i].x<=m+sqrt(ans)) t[++cnt]=a[i]; } sort(t+1,t+cnt+1,cmpy); for(int i=1;i<=cnt;i++) { for(int j=i+1;j<=cnt;j++) { if(t[j].y>t[i].y+sqrt(ans)) break; ans=min(ans,dis(t[j],t[i])); } } } signed main() { scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y); sort(a+1,a+n+1,cmpx); solve(1,n); cout<<(long long)ans< return 0; } 全家桶 typedef double db; const db eps=1e-10; struct V{ db x,y; }; #define il inline /*向量之间运算*/ il bool operator ==(const V &a,const V &b) {return fabs(a.x-b.x)<=eps&&fabs(a.y-b.y)<=eps;} il bool operator !=(const V &a,const V &b) {return !(a==b);} il V operator +(const V &a,const V &b) {return {a.x+b.x,a.y+b.y};} il V operator -(const V &a,const V &b) {return {a.x-b.x,a.y-b.y};} il V operator *(const V &a,const db &x) {return {a.x*x,a.y*x};} il V operator *(const db &x,const V &a) {return {a.x*x,a.y*x};} il V operator /(const V &a,const db &x) {return {a.x/x,a.y/x};} il db operator *(const V &a,const V &b) {return a.x*b.x+a.y*b.y;} il db operator ^(const V &a,const V &b) {return a.x*b.y-a.y*b.x;} il db len(const V &a) {return sqrt(a*a);} il V mid(const V &a,const V &b) {return {(a.x+b.x)/2,(a.y+b.y)/2};} il V cui(const V &a) {return {a.y,-a.x};} il V dw(const V &a) {return a/len(a);} /*角度*/ il db tri_S(const V &a,const V &b,const V &c) {return fabs((a-c)^(b-c))/2;} il db angle(const V &a,const V &b) {return acos(a*b/len(a)/len(b));} //以下均为角 BAC. il bool zhi(const V &a,const V &v,const V &c) {return fabs((b-a)*(c-a))<=eps;} il bool dun(const V &a,const V &b,const V &c) {return (b-a)*(c-a)<-eps;} il bool rui(const V &a,const V &b,const V &c) {return (b-a)*(c-a)>eps;} il V turn(const V &a,db t){ db s=sin(t),c=cos(t); return {a.x*c-a.y*s,a.x*s+a.y*c}; } /*线*/ struct line{ V d,a,b; }; inline line trans(db a,db b,db c,db d) { V dd={c-a,d-b},x={a,b},y={c,d}; dd=dw(dd); return {dd,x,y}; } inline line trans(const V &a,const V &b) { V dd={b.x-a.x,b.y-a.y};dd=dw(dd); return {dd,a,b}; } /*点和线的关系*/ il V cui(const V &o,const line &l) {return ((o-l.a)*l.d)*l.d+l.a;} il V duichen(const V &o,const line &l) { V qwq=cui(o,l); return {2*qwq.x-o.x,2*qwq.y-o.y}; } il db dis(const V &o,const line &l,int op=0) { if(op&&(dun(l.a,o,l.b)||dun(l.b,o,l.a))) return min(len(l.a-o),len(l.b-o)); else return fabs((l.a-o)^(l.b-o))/len(l.b-l.a); } il bool on_line(const line &l,const V &o) {return fabs((o-l.a)^(l.b-l.a)) il bool on_seg(const line &l,const V &o) {return fabs(len(o-l.a)+len(o-l.b)-len(l.b-l.a)) il int pos(const line &l,const V &o) { if(!on_line(l,o)) { if((o-l.a)^l.d<-eps) return 1;//clockwise else return 2;//counter clockwise } if((o-l.a)*(o-l.b)<-eps) return 5;//on else if(len(o-l.a)>len(o-l.b)) return 3;//front else return 4;//back } /*线和线*/ //线和线 il bool gongxian(const line &a,const line &b) {return fabs(a.d^b.d) il bool cuizhi (const line &a,const line &b) {return fabs(a.d*b.d) il bool xdjiao(const line &u,const line &v)//拼音太长缩写了>_< { if(min(u.a.x,u.b.x)>max(v.a.x,v.b.x)+eps||max(u.a.x,u.b.x) if(min(u.a.y,u.b.y)>max(v.a.y,v.b.y)+eps||max(u.a.y,u.b.y) return ((u.a-v.a)^v.d)*((u.b-v.a)^v.d) } il V jiaodian(const line &u,const line &v) { double k=((v.a-u.a)^v.d)/(u.d^v.d); return k*u.d+u.a; } il line pingfen(const V &a,const V &b,const V &c)//角 BAC { int d1=dw(b-a),d2=dw(c-a); int d=(d1+d2)/2; return (line){d,a,a+d}; } /*多边形*/ il int in_poly(V *a,int n,V o) { int res=0;a[n+1]=a[1]; for(int i=1;i<=n;i++) { V u=a[i],v=a[i+1]; if(on_seg(trans(u,v),o)) return 1; if(abs(u.y-v.y) if(max(u.y,v.y) if(min(u.y,v.y)>o.y-eps) continue; double x=u.x+(o.y-u.y)/(v.y-u.y)*(v.x-u.x); if(x } return res?2:0; } il double S(V *a,int n) { db res=0; for(int i=1;i<=n;i++) res+=(a[i]^a[i%n+1]); return res/2; } il int is_convex(V *a,int n) { a[0]=a[n],a[n+1]=a[1]; int op=0; for(int i=1;i<=n;i++) { V x=a[i]-a[i-1],y=a[i+1]-a[i]; if(abs(x^y) int np=((x^y)>0)?1:-1; if(!op) op=np; else if(op!=np) return 0; } return 1; } /*凸包*/ V Q[N];int tp; bool cmp(V a,V b) { if(a.x==b.x) return a.y else return a.x } void andrew(V *a,int n) { sort(a+1,a+n+1,cmp); Q[++tp]=a[1]; for(int i=2;i<=n;Q[++tp]=a[i],i++) while(tp>1&&((Q[tp]-Q[tp-1])^(a[i]-Q[tp])) int pos=tp; for(int i=n-1;i;Q[++tp]=a[i],i--) while(tp>pos&&((Q[tp]-Q[tp-1])^(a[i]-Q[tp])) tp--; } /*旋转卡壳*/ int ans; void find() { int now=2; for(int i=1;i<=tp;i++) { V a=Q[i],b=Q[i%tp+1]; while(Dis(a,b,Q[now%tp+1])>Dis(a,b,Q[now])) now=now%tp+1; ans=max(ans,dis(a,Q[now])); ans=max(ans,dis(b,Q[now])); } } /*半平面交*/ struct line { V a,b,d; double angle; }a[N]; line trans(V a,V b) { double res=atan2((b-a).y,(b-a).x);V d=(b-a)/len(b-a); return {a,b,d,res}; } V jiaodian(line a,line b) { double k=((b.a-a.a)^(b.d))/(a.d^b.d); return a.a+(k*a.d); } bool cmp(line x,line y) { if(fabs(x.angle-y.angle)>eps) return x.angle else return ((y.a-x.a)^(y.b-x.a))>eps; } bool check(line a,line b,line c) { V p=jiaodian(b,c); return (a.d^(p-a.a))<-eps; } line Q[N]; int h=1,t=0,tot; V ans[N]; void solve() { sort(a+1,a+tot+1,cmp); int cnt=1; for(int i=2;i<=tot;i++) if(fabs(a[i].angle-a[i-1].angle)>eps) a[++cnt]=a[i]; tot=cnt; Q[++t]=a[1],Q[++t]=a[2]; for(int i=3;i<=tot;i++) { while(h while(h Q[++t]=a[i]; } while(h while(h int qwq=0; for(int i=h;i if(t-h>1) ans[++qwq]=jiaodian(Q[h],Q[t]); tot=qwq; } int main() { int n=read();tot=0; for(int i=1;i<=n;i++) { int m=read(); for(int j=1;j<=m;j++) b[j].x=read(),b[j].y=read(); for(int j=1;j<=m;j++) a[++tot]=trans(b[j],b[j%m+1]); } solve(); double res=0; for(int i=1;i<=tot;i++) res+=(ans[i]^ans[i%tot+1]); printf("%.3lf\n",res/2); return 0; } 更新日志 2020/04/19 一代初稿 2021/01/29 二代初稿 2022/08/15 几乎重构了整篇文章。 2023/02/14 重构了一些数据结构板子。 2023/10/19 再次重构,优化模板代码的可迁移性,删除了部分过于基础的模板。 重写了几乎所有的代码,现在应该能保证正确性,且码风差不多统一了。 缺什么东西可以评论区把 yxcat 抓回来加。