线段树
https://www.luogu.com.cn/problem/P3373
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4e5+77;
ll tr[N],ch[N],jia[N],a[N];
int n,m,mod;
void update(int u)
{
tr[u]=(tr[u<<1]+tr[u<<1|1])%mod;
}
void pushdown(int u,int st,int ed)
{
int mid=st+ed>>1;
if(ch[u]!=1)
{
(tr[u<<1]*=ch[u])%=mod; (tr[u<<1|1]*=ch[u])%=mod;
(ch[u<<1]*=ch[u])%=mod; (ch[u<<1|1]*=ch[u])%=mod; (jia[u<<1]*=ch[u])%=mod; (jia[u<<1|1]*=ch[u])%=mod;
ch[u]=1;
}
if(jia[u]!=0)
{
(tr[u<<1]+=(mid-st+1)*jia[u])%=mod; (tr[u<<1|1]+=(ed-mid)*jia[u])%=mod; (jia[u<<1]+=jia[u])%=mod,(jia[u<<1|1]+=jia[u])%=mod,jia[u]=0;
}
}
void build(int u,int st,int ed)
{
if(st==ed)
{
tr[u]=a[st]; return;
}
ch[u]=1;
int mid=st+ed>>1;
build(u<<1,st,mid); build(u<<1|1,mid+1,ed);
update(u);
}
void mul(int u,int st,int ed,int l,int r,int t)
{
if(l<=st&&ed<=r)
{
(tr[u]*=t)%=mod; (jia[u]*=t)%=mod; (ch[u]*=t)%=mod; return;
}
pushdown(u,st,ed);
int mid=st+ed>>1;
if(l<=mid) mul(u<<1,st,mid,l,r,t);
if(r>mid) mul(u<<1|1,mid+1,ed,l,r,t);
update(u);
}
void add(int u,int st,int ed,int l,int r,int t)
{
if(l<=st&&ed<=r)
{
(tr[u]+=t*(ed-st+1)%mod)%=mod; (jia[u]+=t)%=mod; return;
}
pushdown(u,st,ed);
int mid=st+ed>>1;
if(l<=mid) add(u<<1,st,mid,l,r,t);
if(r>mid) add(u<<1|1,mid+1,ed,l,r,t);
update(u);
}
ll query(int u,int st,int ed,int l,int r)
{
if(l<=st&&ed<=r)
{
return tr[u];
}
pushdown(u,st,ed);
int mid=st+ed>>1,ret=0;
if(l<=mid) (ret+=query(u<<1,st,mid,l,r))%=mod;
if(r>mid) (ret+=query(u<<1|1,mid+1,ed,l,r))%=mod;
return ret;
}
int main()
{
scanf("%d%d%d",&n,&m,&mod);
for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
build(1,1,n);
while(m--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
int t;
scanf("%d",&t);
mul(1,1,n,x,y,t);
}
else if(op==2)
{
int t;
scanf("%d",&t);
add(1,1,n,x,y,t);
}
else
{
printf("%lld\n",query(1,1,n,x,y));
}
}
}
树状数组
https://www.luogu.com.cn/problem/P3373
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+77;
int n,m,tr[N];
void ins(int x,int t)
{
for(int i=x; i<=n; i+=i&-i) tr[i]+=t;
}
int query(int x)
{
int ret=0;
for(int i=x; i; i-=i&-i) ret+=tr[i];
return ret;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,x; i<=n; i++) scanf("%d",&x),ins(i,x);
while(m--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1) ins(x,y);else printf("%d\n",query(y)-query(x-1));
}
}
dijkstra
https://www.luogu.com.cn/problem/P4779
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+77;
int d[N],ls[N],n,m,s,b[N],cnt;
struct E
{
int to,next,v;
}e[N<<1];
void add(int u,int v,int val)
{
e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt; e[cnt].v=val;
}
struct node
{
int id,v;
friend bool operator < (node x,node y)
{
return x.v>y.v;
}
};
void dij()
{
memset(d,0x3f,sizeof(d));
d[s]=0;
priority_queue<node> q; q.push((node){s,0});
while(!q.empty())
{
node p=q.top(); q.pop();
int u=p.id;
if(b[u]) continue;//这个一定要在外面判
b[u]=1;
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].to; if(b[v]) continue;
if(d[u]+e[i].v<d[v])
{
d[v]=d[u]+e[i].v; q.push((node){v,d[v]});
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1,x,y,z; i<=m; i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z);
dij();
for(int i=1; i<=n; i++) printf("%d ",d[i]);
}
三分
https://www.luogu.com.cn/problem/P3382
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;
const int N=20;
double a[N],l,r;
int n;
double F(double x)
{
double yjy=0;
for(int i=0; i<=n; i++) yjy=yjy*x+a[i];
return yjy;
}
int main()
{
scanf("%d%lf%lf",&n,&l,&r);
for(int i=0; i<=n; i++) scanf("%lf",&a[i]);
while(r-l>=eps)
{
double mid=(l+r)/2;
if(F(mid+eps)>F(mid-eps)) l=mid;else r=mid;
}
printf("%.5lf",r);
}
矩阵树定理
https://www.luogu.com.cn/problem/P4111
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=207,mod=1000000000;
int n,m,tot;
ll f[N][N],Map[N][N];
int read()
{
int x = 0, k = 1;
char c;
c = getchar();
while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * k;
}
void add(int u,int v)
{
if(u>v) return;
f[u][u]++,f[v][v]++,f[u][v]--,f[v][u]--;
}
ll Gauss()
{
ll ans=1;
for(int i=1; i<tot; i++)
{
for(int j=i+1; j<tot; j++) while(f[j][i])
{
ll t=f[i][i]/f[j][i];
for(int k=i; k<tot; k++) f[i][k]=(f[i][k]-t*f[j][k]+mod)%mod;
swap(f[i],f[j]);
ans=-ans;
}
ans=(ans*f[i][i])%mod;
}
return ans;
}
int main()
{
n=read(),m=read();
for(int i = 1; i <= n; i ++)
{
char c;
for(int j = 1; j <= m; j ++)
{
cin >> c;
if(c == '.') Map[i][j] = ++ tot;
}
}
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
{
int tem, u;
if(!(u = Map[i][j])) continue;
if(tem = Map[i - 1][j]) add(u, tem);
if(tem = Map[i + 1][j]) add(u, tem);
if(tem = Map[i][j - 1]) add(u, tem);
if(tem = Map[i][j + 1]) add(u, tem);
}
printf("%lld", (Gauss()+mod)%mod);
}
树链剖分求LCA
https://www.luogu.com.cn/problem/solution/P3379
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+77;
int dep[N],fa[N],n,m,root,top[N],ls[N],cnt,id[N],son[N],siz[N],dfn[N],tot;
struct E
{
int to,next;
}e[N<<1];
void add(int u,int v)
{
e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt;
}
void dfs1(int u)
{
int maxson=0;
dep[u]=dep[fa[u]]+1;
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].to; if(v==fa[u]) continue;
fa[v]=u; dfs1(v); siz[u]+=siz[v];
if(siz[v]>maxson) son[u]=v,maxson=siz[v];
}
siz[u]++;
}
void dfs2(int u,int topf)
{
dfn[u]=++tot; id[tot]=u;
top[u]=topf;
if(!son[u]) return;
dfs2(son[u],topf);
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
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]];
}
if(dep[x]<dep[y]) swap(x,y); return y;
}
int main()
{
scanf("%d%d%d",&n,&m,&root);
for(int i=1,x,y; i<n; i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
// fa[root]=root;
dfs1(root); dfs2(root,root);
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
}
KMP
https://www.luogu.com.cn/problem/P3375
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+77;
char s1[N],s2[N];
int nxt[N];
int main()
{
scanf("%s%s",s1,s2);
int l1=strlen(s1),l2=strlen(s2);
for(int i=1,j=0; i<l2; i++)
{
while(s2[i]!=s2[j]&&j) j=nxt[j];
if(s2[i]==s2[j]) j++;
nxt[i+1]=j;
}
for(int i=0,j=0; i<l1; i++)
{
while(s1[i]!=s2[j]&&j) j=nxt[j];
if(s1[i]==s2[j]) j++;
if(j>=l2) printf("%d\n",i-j+2);
}
for(int i=1; i<=l2; i++) printf("%d ",nxt[i]);
}
差分约束
https://www.luogu.com.cn/problem/P5960
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+77;
int n,m,d[N],b[N],p[N],ls[N],cnt;
struct E
{
int to,next,v;
}e[N<<1];
void add(int u,int v,int val)
{
e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt; e[cnt].v=val;
}
bool spfa()
{
memset(d,0x3f,sizeof(d));
queue<int> q; q.push(n+1);
d[n+1]=0; b[n+1]=1; p[n+1]++;
while(!q.empty())
{
int u=q.front(); q.pop();
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].to;
if(d[u]+e[i].v<d[v])
{
d[v]=d[u]+e[i].v;
if(!b[v])
{
q.push(v),b[v]=1,p[v]++;
if(p[v]>=n) return 0;
}
}
}
b[u]=0;
}
return 1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,x,y,z; i<=m; i++) scanf("%d%d%d",&x,&y,&z),add(y,x,z);
for(int i=1; i<=n; i++) add(n+1,i,0);
if(!spfa()) printf("NO");
else for(int i=1; i<=n; i++) printf("%d ",d[i]);
}
矩阵快速幂
https://www.luogu.com.cn/problem/P3390
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=107,mod=1e9+7;
struct M
{
ll a[N][N]; int n;
void _1()
{
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j]=0;
for(int i=1; i<=n; i++) a[i][i]=1;
}
void clear()
{
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j]=0;
}
}A;
int n;ll k;
M mul(M x,M y)
{
M t; t.n=n; t.clear();
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) for(int k=1; k<=n; k++)
(t.a[i][j]+=(x.a[i][k]*y.a[k][j])%mod)%=mod;
return t;
}
M power(M x,ll t)
{
M b; b.n=x.n;
b._1();
while(t)
{
if(t&1) b=mul(b,x);
x=mul(x,x); t>>=1;
}
return b;
}
int main()
{
scanf("%d%lld",&n,&k);
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) scanf("%lld",&A.a[i][j]);
A.n=n;
A=power(A,k);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++) printf("%lld ",A.a[i][j]);
printf("\n");
}
}
tarjan(强连通)
https://www.luogu.com.cn/problem/P3387
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+77;
int X[N],Y[N],n,m,cnt,Cnt,ls[N],Ls[N],low[N],dfn[N],tot,s[N],top,id,c[N],sum[N],f[N],a[N],ans,d[N],b[N];
struct edge
{
int to,next;
}E[N];
void Add(int u,int v)
{
E[++Cnt].to=v; E[Cnt].next=Ls[u]; Ls[u]=Cnt; X[Cnt]=u,Y[Cnt]=v;
}
void tarjan(int u)
{
dfn[u]=low[u]=++tot; b[u]=1;
s[++top]=u;
for(int i=Ls[u]; i; i=E[i].next)
{
int v=E[i].to;
if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
else if(b[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
id++;
while(s[top+1]!=u)
{
c[s[top]]=id; sum[id]+=a[s[top]]; b[s[top]]=0; top--;
}
}
}
edge e[N];
void add(int u,int v)
{
if(u==v) return;
e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt;
d[v]++;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
for(int i=1,x,y; i<=m; i++) scanf("%d%d",&x,&y),Add(x,y);
for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i);
for(int i=1; i<=m; i++) add(c[X[i]],c[Y[i]]);
queue<int> q;
for(int i=1; i<=id; i++)
{
if(d[i]==0) q.push(i);
f[i]=sum[i]; ans=max(f[i],ans);
}
while(!q.empty())
{
int u=q.front(); q.pop();
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].to;
f[v]=max(f[v],f[u]+sum[v]); d[v]--;
if(!d[v]) q.push(v);
ans=max(f[v],ans);
}
}
printf("%d",ans);
}
点双
https://www.luogu.com.cn/problem/P3388
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+77;
int dfn[N],low[N],ls[N],f[N],cnt=0,ccnt=0,n,m;
bool cut[N];
struct E
{
int to,next;
}e[N];
void add(int u,int v)
{
e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt;
}
void tarjan(int u)
{
dfn[u]=1;
dfn[u]=low[u]=++cnt;
int rd=0;
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].to;
if(!dfn[v])
{
f[v]=f[u];
tarjan(e[i].to);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&u!=f[u]) cut[u]=1;
if(u==f[u]) rd++;
}
else low[u]=min(low[u],dfn[v]);
}
if(rd>1&&u==f[u]) cut[u]=1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
for(int i=1; i<=n; i++) f[i]=i;
for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i);
for(int i=1; i<=n; i++) ccnt+=cut[i];
printf("%d\n",ccnt);
for(int i=1; i<=n; i++) if(cut[i])printf("%d ",i);
}
线性基
https://www.luogu.com.cn/problem/P3812
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=60;
ll _2[N],a[N];
bool bz=0;
int n;
void ins(ll x)
{
int i=0;
while(_2[i]<=x) i++;
for(int j=i; j>=0; j--) if((x&_2[j])!=0)
{
if(!a[j])
{
a[j]=x; break;
}
else x^=a[j];
}
if(x==0) bz=1;
}
ll qmax()
{
ll x=0;
for(int i=51; i>=0; i--) if((x&_2[i])==0)
x=max(x,x^a[i]);
return x;
}
int main()
{
scanf("%d",&n);
_2[0]=1;
for(int i=1; i<=52; i++) _2[i]=_2[i-1]*2;
for(ll i=1,x; i<=n; i++) scanf("%lld",&x),ins(x);
printf("%lld",qmax());
}
exgcd
https://www.luogu.com.cn/problem/P5656
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
void exgcd(ll &x,ll &y,ll a,ll b)
{
if(b==0)
{
x=1,y=0; return ;
}
exgcd(x,y,b,a%b);
int t=x; x=y; y=t-a/b*x;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll a,b,c,d;
scanf("%lld%lld%lld",&a,&b,&c); d=gcd(a,b);
if(c%d!=0)
{
printf("-1\n"); continue;
}
ll x=0,y=0,k=0,p=b/d,q=a/d;
exgcd(x,y,a,b); x*=c/d,y*=c/d;
if(x<=0) k=ceil((1.0-x)/p),x+=p*k,y-=q*k;
else if(x>0) k=(x-1)/p,x-=p*k,y+=q*k;
if(y>0) printf("%lld %lld %lld %lld %lld\n",(y-1)/q+1,x,(y-1)%q+1,x+(y-1)/q*p,y);
else printf("%lld %lld\n",x,y+q*(ll)ceil((1.0-y)/q));
}
}
边双
void tarjan(int u,int fa){
dfn[u] = low[u] = ++tim;
for(int i = head[u];i != -1;i = e[i].next){
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])//边双充要条件
vis[i] = vis[i ^ 1] = 1;
}else
low[u] = min(low[u],dfn[v]);
}
}
树上差分(前缀和)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+7,inf=1e18;
vector<int> e[N],dep,ans;
int fa[N][23];
void dfs1(int u)
{
for(int v:e[u])
{
if(v==fa[u][0]) continue;
dep[v]=dep[u]+1;
fa[v][0]=u;
dfs1(v);
}
}
void dfs2(int u)
{
for(int v:e[u])
{
if(v==fa[u][0]) continue;
ans[v]+=ans[u];
dfs2(v);
}
}
void lca(int u,int v)
{
int x=u,y=v;
if(dep[u]<dep[v]) swap(u,v),swap(x,y);
if(dep[u]!=dep[v])
{
for(int i=20; i>=0; i--)
{
if(dep[fa[u][i]]>dep[v])
u=fa[u][i];
}
if(fa[u][0]==v)
{
ans[u]++;
for(auto t:e[x])
if(t!=fa[x][0])
ans[t]--;
return;
}
u=fa[u][0];
}
for(int i=20; i>=0; i--)
{
if(fa[u][i]!=fa[v][i])
{
u=fa[u][i];
v=fa[v][i];
}
}
ans[u]++;
ans[v]++;
for(auto t:e[x])
if(t!=fa[x][0])
ans[t]--;
for(auto t:e[y])
if(t!=fa[y][0])
ans[t]--;
}
void O_o()
{
int n,m;
cin>>n>>m;
dep.resize(n+1);
ans.resize(n+1);
vector<array<int,2>> p;
for(int i=1; i<n; i++)
{
int x,y;
cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
p.push_back({x,y});
}
dep[1]=1;
dfs1(1);
for(int i=1; i<=20; i++)
{
for(int u=1; u<=n; u++)
{
fa[u][i]=fa[fa[u][i-1]][i-1];
}
}
for(int i=1; i<=m; i++)
{
int x,y;
cin>>x>>y;
if(x==y) continue;
lca(x,y);
}
dfs2(1);
for(int i=n-1; i>=1; i--)
{
auto[x,y]=p[i-1];
if(dep[x]<dep[y]) swap(x,y);
if(ans[x]==m)
{
cout<<i<<"\n";
return;
}
}
cout<<"-1\n";
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cout<<fixed<<setprecision(2);
int T=1;
// cin>>T;
while(T--)
{
O_o();
}
}