模板
数学
乘法逆元
递推求乘法逆元
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=3000010;
ll inv[N],n,p;
int main()
{
scanf("%lld%lld",&n,&p);
inv[1]=1;
puts("1");
for(ll i=2;i<=n;i++){
inv[i]=(p-p/i)*inv[p%i]%p;
printf("%lld\n",inv[i]);
}
}
乘法逆元求组合数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+50;
const ll mod=998244353;
ll inv[N],fac[N];
ll qbow(ll a,ll b){
ll ans=1;
while(b){
if(b&1)
ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans;
}
void init(){
fac[0]=1;
for(int i=1;i<N;i++){
fac[i]=fac[i-1]*i%mod;
}
inv[N-1]=qbow(fac[N-1],mod-2);
for(int i=N-2;i>=0;i--){
inv[i]=inv[i+1]*(i+1)%mod;
}
}
ll C(int n,int m){
if(m>n){
return 0;
}
if(m==0)
return 1;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
init();
int n,m;
scanf("%d%d",&n,&m);
printf("%lld\n",C(n,m));
}
矩阵
矩阵快速幂
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e2+50;
const int Mod=1e9+7;
ll n,k;
struct Matrix{
ll a[N][N];
Matrix(){memset(a,0,sizeof(a));}
Matrix operator *(const Matrix &b)const{
Matrix res;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
for(int k=1;k<=n;++k){
res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j])%Mod;
}
}
}
return res;
}
}A,B;
void qbow(ll k){
while(k){
if(k&1) B=B*A;
A=A*A;
k>>=1;
}
}
int main()
{
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
scanf("%lld",&A.a[i][j]);
}
}
for(int i=1;i<=n;++i) B.a[i][i]=1;
qbow(k);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
printf("%lld ",B.a[i][j]);
}
printf("\n");
}
return 0;
}
矩阵加速
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+50;
const int M=1e5+50;
const ll Mod=1e9+7;
inline ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
struct Matrix{
ll a[4][4];
Matrix(){memset(a,0,sizeof(a));}
Matrix operator *(const Matrix &b)const{
Matrix res;
for(int i=1;i<=3;++i){
for(int j=1;j<=3;++j){
for(int k=1;k<=3;++k){
res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j])%Mod;
}
}
}
return res;
}
}A,B;
ll t,n;
void qbow(ll k){
while(k){
if(k&1) B=B*A;
A=A*A;
k>>=1;
}
}
int main()
{
t=read();
while(t--){
n=read();
if(n<=3){
printf("1\n");
continue;
}
memset(A.a,0,sizeof(A.a));
memset(B.a,0,sizeof(B.a));
for(int i=1;i<=3;++i) B.a[i][i]=1;
A.a[1][1]=A.a[3][1]=A.a[1][2]=A.a[2][3]=1;
qbow(n-1);
printf("%lld\n",B.a[1][1]);
}
return 0;
}
高斯消元
约旦
#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int N=110;
db a[N][N];
int n;
bool Gauss_Jordan(){
for(int i=1;i<=n;++i){
int mx=i;
for(int j=i+1;j<=n;++j){
mx=fabs(a[j][i])>fabs(a[mx][i])?j:mx;
}
if(mx!=i) swap(a[i],a[mx]);
if(!a[i][i]) return false;
for(int j=1;j<=n;++j){
if(i==j) continue;
db res=a[j][i]/a[i][i];
for(int k=i+1;k<=n+1;++k){
a[j][k]-=a[i][k]*res;
}
}
}
return true;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i){
for(int j=1;j<=n+1;++j){
scanf("%lf",&a[i][j]);
}
}
if(Gauss_Jordan()){
for(int i=1;i<=n;++i){
printf("%.2lf\n",a[i][n+1]*1.0/a[i][i]);
}
}else{
printf("No Solution\n");
}
return 0;
}
快速幂
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll work(ll a,ll b,ll m)
{
ans=1;
while(b>0)
{
if(b%2!=0)
ans=ans*a%m;
a=a*a%m;
b=b>>1;
}
ans %= m;
return ans;
}
线性筛
#include<bits/stdc++.h>
using namespace std;
const int N=1e8,M=5*1e6;
bool is_prime[N+50];
int phi[N+50],prime[M+50];
void pre(){
memset(is_prime,1,sizeof(is_prime));
int cnt=0;
is_prime[1]=0;
phi[1]=1;
for(int i=2;i<=N;i++){
if(is_prime[i]){
prime[++cnt] = i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&i*prime[j]<=N;j++){
is_prime[i*prime[j]]=0;
if(i%prime[j]){
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}else{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
}
}
int n,q,x;
int main()
{
pre();
scanf("%d%d",&n,&q);
for(int i=1;i<=q;++i){
scanf("%d",&x);
printf("%d\n",prime[x]);
}
return 0;
}
树形结构
静态区间第K大或小
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=2e5+50;
const int M=1e5+50;
const int Mod=1e9+7;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int n,q,m,cnt;
int a[N],b[N],id[N];
int ans[N<<5],L[N<<5],R[N<<5];
int build(int l,int r){
int p=++cnt;
ans[p]=0;
int mid=(l+r)>>1;
if(l<r){
L[p]=build(l,mid);
R[p]=build(mid+1,r);
}
return p;
}
int update(int pre,int l,int r,int x){
int p=++cnt;
L[p]=L[pre];R[p]=R[pre];ans[p]=ans[pre]+1;
int mid=(l+r)>>1;
if(l<r){
if(x<=mid) L[p]=update(L[pre],l,mid,x);
else R[p]=update(R[pre],mid+1,r,x);
}
return p;
}
int query(int nx,int ny,int l,int r,int k){
if(l>=r) return l;
int x=ans[L[ny]]-ans[L[nx]];
int mid=(l+r)>>1;
if(x>=k) return query(L[nx],L[ny],l,mid,k);
else return query(R[nx],R[ny],mid+1,r,k-x);
}
int main()
{
n=read(),q=read();
for(int i=1;i<=n;++i){
a[i]=read();
b[i]=a[i];
}
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-b-1;
id[0]=build(1,m);
for(int i=1;i<=n;++i){
int it=lower_bound(b+1,b+m+1,a[i])-b;
id[i]=update(id[i-1],1,m,it);
}
while(q--){
int l=read(),r=read(),k=read();
printf("%d\n",b[query(id[l-1],id[r],1,m,k)]);
}
return 0;
}
普通平衡树
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 1e5 + 50;
const int M = 1e5 + 50;
const int Mod = INT_MAX;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int root, sum;
int siz[N], num[N], v[N], rd[N], son[N][2];
void push_up(int p)
{
siz[p] = siz[son[p][0]] + siz[son[p][1]] + num[p];
}
void rotate(int &p, int d)
{
int k = son[p][d ^ 1];
son[p][d ^ 1] = son[k][d];
son[k][d] = p;
push_up(p);
push_up(k);
p = k;
}
void ins(int &p, int x)
{
if (!p)
{
++sum;
p = sum;
num[p] = siz[p] = 1;
rd[p] = rand();
v[p] = x;
return;
}
if (v[p] == x)
{
num[p]++;
siz[p]++;
return;
}
int d = x > v[p];
ins(son[p][d], x);
if (rd[p] < rd[son[p][d]])
rotate(p, d ^ 1);
push_up(p);
}
void del(int &p, int x)
{
if (!p)
return;
if (x < v[p])
del(son[p][0], x);
else if (x > v[p])
del(son[p][1], x);
else
{
if (!son[p][0] && !son[p][1])
{
num[p]--;
siz[p]--;
if (!num[p])
p = 0;
}
else if (son[p][0] && !son[p][1])
{
rotate(p, 1);
del(son[p][1], x);
}
else if (!son[p][0] && son[p][1])
{
rotate(p, 0);
del(son[p][0], x);
}
else
{
int d = rd[son[p][0]] > rd[son[p][1]];
rotate(p, d);
del(son[p][d], x);
}
}
push_up(p);
}
int rk(int p, int x)
{
if (!p)
return 1;
if (v[p] > x)
return rk(son[p][0], x);
else if (v[p] == x)
return siz[son[p][0]] + 1;
else
return siz[son[p][0]] + num[p] + rk(son[p][1], x);
}
int fd(int p, int x)
{
if (!p)
return 0;
if (siz[son[p][0]] >= x)
return fd(son[p][0], x);
else if (siz[son[p][0]] + num[p] < x)
return fd(son[p][1], x - siz[son[p][0]] - num[p]);
else
return v[p];
}
int pre(int p, int x)
{
if (!p)
return -Mod;
if (v[p] >= x)
return pre(son[p][0], x);
else
return max(v[p], pre(son[p][1], x));
}
int suc(int p, int x)
{
if (!p)
return Mod;
if (v[p] <= x)
return suc(son[p][1], x);
else
return min(v[p], suc(son[p][0], x));
}
int main()
{
srand(time(NULL));
int n = read();
while (n--)
{
int opt = read(), x = read();
if (opt == 1)
ins(root, x);
if (opt == 2)
del(root, x);
if (opt == 3)
printf("%d\n", rk(root, x));
if (opt == 4)
printf("%d\n", fd(root, x));
if (opt == 5)
printf("%d\n", pre(root, x));
if (opt == 6)
printf("%d\n", suc(root, x));
}
return 0;
}
树剖
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
const int N=4e5+50;
ll n,m,r,mod;
struct edge{
ll to,next;
}e[N];
ll head[N],cnt;
void add_edge(int u,int v){
++cnt;
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
ll w[N],wt[N];
ll son[N],id[N],fa[N],dep[N],siz[N],top[N],res;
ll ans[N],lazy_add[N];
ll ls(ll p){return p<<1;}
ll rs(ll p){return p<<1|1;}
void push_up(ll p){
ans[p]=(ans[ls(p)]+ans[rs(p)])%mod;
}
void build(ll p,ll l,ll r){
lazy_add[p]=0;
if(l==r){ans[p]=wt[l];ans[p]=ans[p]>mod?ans[p]%mod:ans[p];return;}
ll mid=(l+r)>>1;
build(ls(p),l,mid);
build(rs(p),mid+1,r);
push_up(p);
}
void change(ll p,ll l,ll r,ll add){
lazy_add[p]=(lazy_add[p]+add)%mod;
ans[p]=(ans[p]+(r-l+1)*add)%mod;
}
void push_down(ll p,ll l,ll r){
ll mid=(l+r)>>1;
change(ls(p),l,mid,lazy_add[p]);
change(rs(p),mid+1,r,lazy_add[p]);
lazy_add[p]=0;
}
void update(ll nx,ll ny,ll l,ll r,ll p,ll k){
if(nx<=l&&r<=ny){
ans[p]+=(r-l+1)*k;
lazy_add[p]+=k;
return;
}
push_down(p,l,r);
ll mid=(l+r)>>1;
if(nx<=mid) update(nx,ny,l,mid,ls(p),k);
if(ny>mid) update(nx,ny,mid+1,r,rs(p),k);
push_up(p);
}
ll query(ll nx,ll ny,ll l,ll r,ll p){
ll res=0;
if(nx<=l&&r<=ny){return ans[p];}
push_down(p,l,r);
ll mid=(l+r)>>1;
if(nx<=mid) res=(res+query(nx,ny,l,mid,ls(p)))%mod;
if(ny>mid) res=(res+query(nx,ny,mid+1,r,rs(p)))%mod;
return res;
}
void update_range(ll x,ll y,ll k){
k%=mod;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(id[top[x]],id[x],1,n,1,k);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(id[x],id[y],1,n,1,k);
}
ll query_range(ll x,ll y){
ll res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res=(res+query(id[top[x]],id[x],1,n,1))%mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
res=(res+query(id[x],id[y],1,n,1))%mod;
return res;
}
void update_tree(ll x,ll z){
update(id[x],id[x]+siz[x]-1,1,n,1,z);
}
ll query_tree(ll x){
return query(id[x],id[x]+siz[x]-1,1,n,1);
}
void dfs1(ll u,ll p){
dep[u]=dep[p]+1;
fa[u]=p;
siz[u]=1;
ll maxn=-1;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v==p) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>maxn) son[u]=v,maxn=siz[v];
}
}
void dfs2(ll u,ll topf){
++res;
id[u]=res;
wt[res]=w[u];
top[u]=topf;
if(!son[u]) return;
dfs2(son[u],topf);
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
ll LCA(ll u,ll v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
if(dep[u]<dep[v]) return u;
return v;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&r,&mod);
for(int i=1;i<=n;++i) scanf("%d",&w[i]);
for(int i=1;i<n;++i){
ll u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs1(r,0);
dfs2(r,r);
build(1,1,n);
for(int i=1;i<=m;++i){
ll opt;
scanf("%d",&opt);
if(opt==1){
ll x,y,z;
scanf("%d%d%d",&x,&y,&z);
update_range(x,y,z);
}else
if(opt==2){
ll x,y;
scanf("%d%d",&x,&y);
printf("%d\n",query_range(x,y));
}else
if(opt==3){
ll x,z;
scanf("%d%d",&x,&z);
update_tree(x,z);
}else{
ll x;
scanf("%d",&x);
printf("%d\n",query_tree(x));
}
}
return 0;
}
LCS
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+50;
int n;
int a[N];
vector<int>pos[N];
ll maxn[N<<2];
ll ls(ll x){return x<<1;}
ll rs(ll x){return x<<1|1;}
void push_up(ll p){
maxn[p]=max(maxn[ls(p)],maxn[rs(p)]);
}
void update(ll nx,ll ny,ll l,ll r,ll p,ll k){
if(nx<=l&&r<=ny){
maxn[p]=max(maxn[p],k);
return;
}
ll mid=(l+r)>>1;
if(nx<=mid) update(nx,ny,l,mid,ls(p),k);
if(ny>mid) update(nx,ny,mid+1,r,rs(p),k);
push_up(p);
}
ll query(ll nx,ll ny,ll l,ll r,ll p){
ll res=0;
if(nx<=l&&r<=ny) return maxn[p];
ll mid=(l+r)>>1;
if(nx<=mid) res=max(res,query(nx,ny,l,mid,ls(p)));
if(ny>mid) res=max(res,query(nx,ny,mid+1,r,rs(p)));
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i){
int x;
scanf("%d",&x);
pos[x].push_back(i);
}
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
if(pos[a[i]].size()==0) continue;
for(int j=pos[a[i]].size()-1;j>=0;--j){
ll res=query(1,pos[a[i]][j],1,n,1);
update(pos[a[i]][j],pos[a[i]][j],1,n,1,res+1);
}
}
printf("%lld\n",query(1,n,1,n,1));
}
并查集
#include<bits/stdc++.h>
using namespace std;
int n,m;
int p[10001];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) p[i]=i;
for(int i=1;i<=m;++i){
int z,x,y;
scanf("%d%d%d",&z,&x,&y);
int px=find(x),py=find(y);
if(z==1){
if(px!=py){
p[px]=py;
}
}else{
if(px==py){
cout<<"Y"<<endl;
}else{
cout<<"N"<<endl;
}
}
}
return 0;
}
LCA
倍增
#include<bits/stdc++.h>
using namespace std;
struct edge
{
int to,next;
};
edge e[500010<<1];
int head[500010],dep[500010],cnt;
int fa[500010][30],f[500010];
int n,m,s;
void add_edge(int u,int v)
{
++cnt;
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void dfs(int now,int p)
{
fa[now][0]=p;
dep[now]=dep[p]+1;
for(int i=1;i<=f[dep[now]];i++)
{
fa[now][i]=fa[fa[now][i-1]][i-1];
}
for(int i=head[now];i;i=e[i].next)
{
if(e[i].to!=p) dfs(e[i].to,now);
}
}
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y])
{
x=fa[x][f[dep[x]-dep[y]]-1];
}
if(x==y) return x;
for(int k=f[dep[y]]-1;k>=0;k--)
{
if(fa[x][k]!=fa[y][k])
{
x=fa[x][k];
y=fa[y][k];
}
}
return fa[x][0];
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
for(int i=1;i<=n;i++)
{
f[i]=f[i-1]+(1<<f[i-1]==i);
}
dfs(s,0);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",LCA(u,v));
}
return 0;
}
DFN序
\[O(1)
\]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 5e5 + 50;
const int M = 1e5 + 50;
const int Mod = 1e9 + 7;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int n, m, r;
int f[N][19], dfn[N];
struct edge
{
int to, nxt;
} e[N << 1];
int head[N], cnt;
void add_edge(int u, int v)
{
++cnt;
e[cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int dns;
void dfs(int u, int p)
{
++dns;
dfn[u] = dns;
f[dns][0] = p;//记住是编号
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == p)
continue;
dfs(v, u);
}
}
int get(int u, int v)
{
return dfn[u] < dfn[v] ? u : v;
}
int lca(int u, int v)
{
if (u == v)
return u;
u = dfn[u], v = dfn[v];
if (u > v)
swap(u, v);
int d = __lg(v - u); //记住是dfn u+1 dfn v 区间 r-l+1 这里常数消掉了
++u;
return get(f[u][d], f[v - (1 << d) + 1][d]);
}
int main()
{
n = read(), m = read(), r = read();
for (int i = 1; i < n; ++i)
{
int u = read(), v = read();
add_edge(u, v);
add_edge(v, u);
}
dfs(r, 0);
for (int i = 1; i <= __lg(n); ++i) //背一下吧
{
for (int j = 1; j + (1 << i) - 1 <= n; ++j)
{
f[j][i] = get(f[j][i - 1], f[j + (1 << i - 1)][i - 1]);
}//合并归并类似。
}
for (int i = 1; i <= m; ++i)
{
int u = read(), v = read();
printf("%d\n", lca(u, v));
}
return 0;
}
增量法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 1e5 + 50;
const int M = 1e5 + 50;
const int Mod = 1e9 + 7;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int n, m, Q;
struct edge
{
int to, nxt;
} e[N << 1];
int head[N], cnt;
void add_edge(int u, int v)
{
++cnt;
e[cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int a[N];
int f[N][19], dfn[N], dns = 0, dep[N];
void dfs(int u, int p)
{
dep[u] = dep[p] + 1;
++dns;
dfn[u] = dns;
f[dns][0] = p;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == p)
continue;
dfs(v, u);
}
}
int get(int u, int v)
{
return dfn[u] < dfn[v] ? u : v;
}
int lca(int u, int v)
{
if (u == v)
return u;
u = dfn[u], v = dfn[v];
if (u > v)
swap(u, v);
u++;
int len = __lg(v - u + 1);
return get(f[u][len], f[v - (1 << len) + 1][len]);
}
struct node
{
int x, y, dis;
} P[N];
int Dist(int u, int v)
{
if (u == -1 || v == -1)
return -1;
int p = lca(u, v);
return dep[u] + dep[v] - 2 * dep[p];
}
void diameter(int i, int c)
{
if (P[c].x == -1)
{
P[c].x = i;
}
else if (P[c].y == -1)
{
P[c].y = i;
P[c].dis = Dist(P[c].x, P[c].y);
}
else
{
int d1 = Dist(P[c].x, i);
int d2 = Dist(P[c].y, i);
if (d1 >= d2 && d1 >= P[c].dis)
{
P[c].y = i;
P[c].dis = d1;
}
else if (d2 >= d1 && d2 >= P[c].dis)
{
P[c].x = i;
P[c].dis = d2;
}
}
}
int col[N], ans;
node query(int l, int r)
{
if (l == r)
return P[col[l]];
int mid = l + r >> 1;
node p = query(l, mid), q = query(mid + 1, r);
int d1 = Dist(p.x, q.x);
int d2 = Dist(p.x, q.y);
int d3 = Dist(p.y, q.x);
int d4 = Dist(p.y, q.y);
int res = max(max(d1, d2), max(d3, d4));
ans = max(ans, res);
res = max(res, max(q.dis, p.dis));
if (res == -1)
return (node){max(p.x, q.x), max(p.y, q.y), res};
if (p.dis == res)
return p;
if (q.dis == res)
return q;
if (d1 == res)
return (node){p.x, q.x, d1};
if (d2 == res)
return (node){p.x, q.y, d2};
if (d3 == res)
return (node){p.y, q.x, d3};
if (d4 == res)
return (node){p.y, q.y, d4};
}
int main()
{
n = read(), m = read(), Q = read();
for (int i = 1; i <= n; ++i)
a[i] = read();
for (int i = 1; i < n; ++i)
{
int u = read(), v = read();
add_edge(u, v);
add_edge(v, u);
}
dfs(1, 0);
int lgn = __lg(n);
for (int j = 1; j <= lgn; ++j)
{
for (int i = 1; i + (1 << j) - 1 <= n; ++i)
{
f[i][j] = get(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
}
memset(P, -1, sizeof(P));
for (int i = 1; i <= n; ++i)
diameter(i, a[i]);
for (int i = 1; i <= Q; ++i)
{
ans = -1;
int k = read();
for (int j = 1; j <= k; ++j)
col[j] = read();
query(1, k);
printf("%d\n", ans > 0 ? ans + 1 : -1);
}
return 0;
}
线段树
区间加
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=4*1e5+50;
ll a[N],ans[N],lazy_add[N];
ll ls(ll x){return x<<1;}
ll rs(ll x){return x<<1|1;}
void push_up(ll p){ans[p]=ans[ls(p)]+ans[rs(p)];}
void build(ll p,ll l,ll r){
lazy_add[p]=0;
if(l==r) {ans[p]=a[l];return;}
ll mid=(l+r)>>1;
build(ls(p),l,mid);
build(rs(p),mid+1,r);
push_up(p);
}
void change(ll p,ll l,ll r,ll add){
lazy_add[p]=lazy_add[p]+add;
ans[p]=ans[p]+(r-l+1)*add;
}
void push_down(ll p,ll l,ll r){
ll mid=(l+r)>>1;
change(ls(p),l,mid,lazy_add[p]);
change(rs(p),mid+1,r,lazy_add[p]);
lazy_add[p]=0;
}
void update(ll nl,ll nr,ll l,ll r,ll p,ll k){
if(nl<=l&&r<=nr){
ans[p]+=k*(r-l+1);
lazy_add[p]+=k;
return;
}
push_down(p,l,r);
ll mid=(l+r)>>1;
if(nl<=mid) update(nl,nr,l,mid,ls(p),k);
if(nr>mid) update(nl,nr,mid+1,r,rs(p),k);
push_up(p);
}
ll query(ll nx,ll ny,ll l,ll r,ll p){
ll res=0;
if(nx<=l&&r<=ny) return ans[p];
push_down(p,l,r);
int mid=(l+r)>>1;
if(nx<=mid) res+=query(nx,ny,l,mid,ls(p));
if(ny>mid) res+=query(nx,ny,mid+1,r,rs(p));
return res;
}
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;++i){
scanf("%lld",&a[i]);
}
build(1,1,n);
while(m--){
ll qs;
scanf("%lld",&qs);
if(qs==1){
ll x,y,k;
scanf("%lld%lld%lld",&x,&y,&k);
update(x,y,1,n,1,k);
}else{
ll x,y;
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(x,y,1,n,1));
}
}
return 0;
}
区间乘
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=4*1e5+50;
ll a[N],ans[N];
ll lazy_add[N];
ll lazy_mul[N];
ll mod;
ll ls(ll x){return x<<1;}
ll rs(ll x){return x<<1|1;}
void push_up(ll p){
ans[p]=ans[ls(p)]+ans[rs(p)];
}
void build(ll p,ll l,ll r)
{
lazy_add[p]=0;
lazy_mul[p]=1;
if(l==r){ans[p]=a[l];return;}
ll mid=(l+r)>>1;
build(ls(p),l,mid);
build(rs(p),mid+1,r);
push_up(p);
}
void change(ll p,ll l,ll r,ll add,ll mul){
lazy_mul[p]=(lazy_mul[p]*mul)%mod;
lazy_add[p]=(lazy_add[p]*mul+add)%mod;
ans[p]=(ans[p]*mul+(r-l+1)*add)%mod;
}
void push_down(ll p,ll l,ll r){
ll mid=(l+r)>>1;
change(ls(p),l,mid,lazy_add[p],lazy_mul[p]);
change(rs(p),mid+1,r,lazy_add[p],lazy_mul[p]);
lazy_add[p]=0;
lazy_mul[p]=1;
}
void update_mul(ll nl,ll nr,ll l,ll r,ll p,ll k){
if(nl<=l&&r<=nr){
ans[p]=(ans[p]*k)%mod;
lazy_add[p]=(lazy_add[p]*k)%mod;
lazy_mul[p]=(lazy_mul[p]*k)%mod;
return;
}
push_down(p,l,r);
ll mid=(l+r)>>1;
if(nl<=mid) update_mul(nl,nr,l,mid,ls(p),k);
if(nr>mid) update_mul(nl,nr,mid+1,r,rs(p),k);
push_up(p);
}
void update_add(ll nl,ll nr,ll l,ll r,ll p,ll k){
if(nl<=l&&r<=nr){
ans[p]=(ans[p]+(r-l+1)*k)%mod;
lazy_add[p]=(lazy_add[p]+k)%mod;
return;
}
push_down(p,l,r);
ll mid=(l+r)>>1;
if(nl<=mid) update_add(nl,nr,l,mid,ls(p),k);
if(nr>mid) update_add(nl,nr,mid+1,r,rs(p),k);
push_up(p);
}
ll query_add(ll nx,ll ny,ll l,ll r,ll p){
ll res=0;
if(nx<=l&&r<=ny) return ans[p];
push_down(p,l,r);
ll mid=(l+r)>>1;
if(nx<=mid) res=(res+query_add(nx,ny,l,mid,ls(p)))%mod;
if(ny>mid) res=(res+query_add(nx,ny,mid+1,r,rs(p)))%mod;
return res;
}
int main()
{
ll n,m;
scanf("%lld%lld%lld",&n,&m,&mod);
for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
ll qs;
scanf("%lld",&qs);
if(qs==1){
ll x,y,k;
scanf("%lld%lld%lld",&x,&y,&k);
update_mul(x,y,1,n,1,k);
}else
if(qs==2){
ll x,y,k;
scanf("%lld%lld%lld",&x,&y,&k);
update_add(x,y,1,n,1,k);
}else
if(qs==3){
ll x,y;
scanf("%lld%lld",&x,&y);
printf("%lld\n",query_add(x,y,1,n,1)%mod);
}
}
return 0;
}
区间不同值
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e6+50;
int n,m;
int a[N],lst[N];
int tree[N<<2],ans[N];
vector<int>vis[N];
struct node{
int l,r,id;
}q[N];
bool cmp(node x,node y){return x.r<y.r;}
int ls(int p){return p<<1;}
int rs(int p){return p<<1|1;}
void push_up(int p){tree[p]=tree[ls(p)]+tree[rs(p)];}
void update(int nx,int ny,int l,int r,int p){
if(nx<=l&&r<=ny){tree[p]=1;return;}
int mid=(l+r)>>1;
if(nx<=mid) update(nx,ny,l,mid,ls(p));
if(ny>mid) update(nx,ny,mid+1,r,rs(p));
push_up(p);
}
void modify(int nx,int ny,int l,int r,int p){
if(nx<=l&&r<=ny){tree[p]=0;return;}
int mid=(l+r)>>1;
if(nx<=mid) modify(nx,ny,l,mid,ls(p));
if(ny>mid) modify(nx,ny,mid+1,r,rs(p));
push_up(p);
}
int query(int nx,int ny,int l,int r,int p){
int res=0;
if(nx<=l&&r<=ny) return tree[p];
int mid=(l+r)>>1;
if(nx<=mid) res+=query(nx,ny,l,mid,ls(p));
if(ny>mid) res+=query(nx,ny,mid+1,r,rs(p));
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;++i) vis[q[i].r].push_back(i);
for(int i=1;i<=n;++i){
if(!lst[a[i]]){
lst[a[i]]=i;
update(i,i,1,n,1);
}else{
modify(lst[a[i]],lst[a[i]],1,n,1);
lst[a[i]]=i;
update(i,i,1,n,1);
}
for(int j=0;j<(int)vis[i].size();++j){
ans[q[vis[i][j]].id]=query(q[vis[i][j]].l,q[vis[i][j]].r,1,n,1);
}
}
for(int i=1;i<=m;++i){printf("%d\n",ans[i]);}
return 0;
}
点分治
k值差
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 1e4 + 50;
const int M = 1e7 + 50;
const int Mod = 1e9 + 7;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int n, m;
struct edge
{
int to, dis, nxt;
} e[N << 1];
int head[N], cnt;
void add_edge(int u, int v, int w)
{
++cnt;
e[cnt].to = v;
e[cnt].dis = w;
e[cnt].nxt = head[u];
head[u] = cnt;
}
bool tf[M];
int q[N];
int dp[N], root, siz[N];
bool vis[N];
int sum;
void getroot(int u, int p)
{
dp[u] = 0;
siz[u] = 1;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == p || vis[v])
continue;
getroot(v, u);
siz[u] += siz[v];
dp[u] = max(dp[u], siz[v]);
}
dp[u] = max(dp[u], sum - dp[u]);
if (dp[u] < dp[root])
root = u;
}
int lst[N], it = 0;
int dis[N];
void exlst(int u, int p)
{
lst[++it] = dis[u];
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == p || vis[v])
continue;
dis[v] = dis[u] + e[i].dis;
exlst(v, u);
}
}
int rev[N];
queue<int> tag;
void count(int u)
{
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (vis[v])
continue;
it = 0;
dis[v] = e[i].dis;
exlst(v, u);
for (int j = 1; j <= m; ++j)
{
for (int k = 1; k <= it; ++k)
{
if (q[j] >= lst[k])
rev[j] |= tf[q[j] - lst[k]];
}
}
for (int j = 1; j <= it; ++j)
if (lst[j] <= M)
tag.push(lst[j]), tf[lst[j]] = 1;
}
while (!tag.empty())
tf[tag.front()] = 0, tag.pop();
}
void solve(int u)
{
vis[u] = 1;
tf[0] = 1;
count(u);
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (vis[v])
continue;
dp[0] = n;
sum = siz[v];
root = 0;
getroot(v, u);
solve(root);
}
}
int main()
{
n = read(), m = read();
for (int i = 1; i < n; ++i)
{
int u = read(), v = read(), w = read();
add_edge(u, v, w);
add_edge(v, u, w);
}
for (int i = 1; i <= m; ++i)
q[i] = read();
dp[root] = n;
sum = n;
getroot(1, 0);
solve(root);
for (int i = 1; i <= m; ++i)
if (rev[i])
puts("AYE");
else
puts("NAY");
return 0;
}
图论
拓扑排序
void TopSort()
{
queue<int>q;
for(int i=1;i<=n;++i){
if(!in[i]){
q.push(i);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
--in[v];
if(!in[v]) q.push(v);
}
}
}
tarjan
int dfn[N], low[N], dns;
int color[N], col;
stack<int> st;
bool ins[N];
void tarjan(int u)
{
low[u] = dfn[u] = ++dns;
st.push(u);
ins[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 (ins[v])
low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u])
{
++col;
while (st.top() != u)
{
color[st.top()] = col;
ins[st.top()] = 0;
st.pop();
}
color[st.top()] = col;
ins[st.top()] = 0;
st.pop();
}
}
2-SAT
拓扑序考虑方案,应排除其后效性
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 2e6 + 50;
const int M = 1e5 + 50;
const int Mod = 1e9 + 7;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int n, m;
struct edge
{
int to, nxt;
} e[N << 1];
int head[N], cnt;
void add_edge(int u, int v)
{
++cnt;
e[cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int dfn[N], low[N], dns;
int color[N], col;
stack<int> st;
bool ins[N];
void tarjan(int u)
{
low[u] = dfn[u] = ++dns;
st.push(u);
ins[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 (ins[v])
low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u])
{
++col;
while (st.top() != u)
{
color[st.top()] = col;
ins[st.top()] = 0;
st.pop();
}
color[st.top()] = col;
ins[st.top()] = 0;
st.pop();
}
}
int main()
{
n = read(), m = read();
for (int i = 1; i <= m; ++i)
{
int u = read(), a = read(), v = read(), b = read();
add_edge(u + n * (a & 1), v + n * (b ^ 1));
add_edge(v + n * (b & 1), u + n * (a ^ 1));
}
for (int i = 1; i <= n + n; ++i)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= n; ++i)
if (color[i] == color[i + n])
{
puts("IMPOSSIBLE");
return 0;
}
puts("POSSIBLE");
for (int i = 1; i <= n; ++i)
{
printf("%d ", color[i] < color[i + n]);
}
return 0;
}
二分图
二分图染色
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=1e5+50;
struct edge{
int to,next;
}e[N<<1];
int head[N<<1],cnt,col[N<<1];
int res[3];
void add_edge(int u,int v){
++cnt;
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
bool flag=0;
queue<int>q;
int ans=0;
for(int i=1;i<=n&&!flag;++i){
if(col[i]) continue;
q.push(i);
res[1]=res[2]=0;
col[i]=1;
res[col[i]]++;
while(!q.empty()){
int x=q.front();
q.pop();
for(int j=head[x];j;j=e[j].next){
int y=e[j].to;
if(col[y]){
if(col[y]==col[x]){
flag=1;
break;
}
}else{
col[y]=3-col[x];
res[col[y]]++;
q.push(y);
}
}
}
ans+=min(res[1],res[2]);
}
if(flag){
printf("Impossible\n");
}else{
printf("%d\n",ans);
}
}
Dijskra
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+50;
struct edge{
int to,dis,next;
}e[N<<2];
int dis[N],head[N],cnt;
bool vis[N];
void add_edge(int u,int v,int w){
++cnt;
e[cnt].dis=w;
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
struct node{
int dis;
int pos;
bool operator <(const node &x)const{
return x.dis<dis;
}
};
priority_queue<node>q;
void dij(int s){
dis[s]=0;
q.push((node){0,s});
while(!q.empty()){
node tmp=q.top();
q.pop();
int d=tmp.dis,x=tmp.pos;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].next){
int y=e[i].to;
if(dis[y]>dis[x]+e[i].dis){
dis[y]=dis[x]+e[i].dis;
if(!vis[y]){
q.push((node){dis[y],y});
}
}
}
}
}
int main()
{
int n,m,s;
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=n;++i) dis[i]=0x3f3f3f3f;
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
dij(s);
for(int i=1;i<=n;++i){
printf("%d ",dis[i]);
}
return 0;
}
SPFA
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+50;
struct edge{
int to,dis,next;
}e[10*N];
int dis[N],head[N],cnt;
bool vis[N];
void add_edge(int u,int v,int w){
++cnt;
e[cnt].dis=w;
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
queue<int>q;
void spfa(int s){
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=e[i].next){
int y=e[i].to;
if(dis[y]>dis[x]+e[i].dis){
dis[y]=dis[x]+e[i].dis;
if(!vis[y]){
q.push(y);
vis[y]=1;
}
}
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) dis[i]=0x3f3f3f3f;
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
spfa(1);
printf("%d",dis[n]);
return 0;
}
SPFA 判断负环
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+50;
const int M=6e3+50;
struct edge{
int to,dis,next;
}e[M];
int head[M],dis[M],res[M],cnt;
bool vis[M];
void init(){
cnt=0;
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(head,0,sizeof(head));
memset(res,0,sizeof(res));
memset(vis,0,sizeof(vis));
}
void add_edge(int u,int v,int w){
++cnt;
e[cnt].to=v;
e[cnt].dis=w;
e[cnt].next=head[u];
head[u]=cnt;
}
int t,n,m;
void spfa(int s){
queue<int>q;
dis[s]=0;
q.push(s);
vis[s]=1;
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=e[i].next){
int y=e[i].to;
if(dis[y]>dis[x]+e[i].dis){
dis[y]=dis[x]+e[i].dis;
res[y]=res[x]+1;
if(res[y]>=n) {
printf("YES\n");
return;
}
if(!vis[y]){
vis[y]=1;
q.push(y);
}
}
}
}
printf("NO\n");
}
int main()
{
scanf("%d",&t);
while(t--){
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(w<0){
add_edge(u,v,w);
}else{
add_edge(u,v,w);
add_edge(v,u,w);
}
}
spfa(1);
}
return 0;
}
网络流
EK
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 2e2 + 50;
const int M = 5e3 + 50;
const int Mod = 1e9 + 7;
#define int long long
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int n, m, s, t;
struct edge
{
int to, dis, nxt;
} e[M << 1];
int head[N], cnt = 1;
void add_edge(int u, int v, int w)
{
++cnt;
e[cnt].to = v;
e[cnt].dis = w;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int flag[N][N];
int pre[N], dis[N];
bool vis[N];
int bfs()
{
memset(vis, 0, sizeof(vis));
queue<int> q;
q.push(s);
vis[s] = 1;
dis[s] = Mod << 1;
while (!q.empty())
{
int x = q.front();
q.pop();
for (int i = head[x]; i; i = e[i].nxt)
{
if (e[i].dis == 0)
continue;
int y = e[i].to;
if (vis[y])
continue;
dis[y] = min(dis[x], e[i].dis);
q.push(y);
vis[y] = 1;
pre[y] = i;
if (y == t)
return 1;
}
}
return 0;
}
int ans = 0;
void update()
{
int x = t;
while (x != s)
{
int y = pre[x];
e[y].dis -= dis[t];
e[y ^ 1].dis += dis[t];
x = e[y ^ 1].to;
}
ans += dis[t];
}
signed main()
{
n = read(), m = read(), s = read(), t = read();
for (int i = 1; i <= m; ++i)
{
int u = read(), v = read(), w = read();
if (!flag[u][v])
{
add_edge(u, v, w);
add_edge(v, u, 0);
flag[u][v] = cnt;
}
else
{
e[flag[u][v] - 1].dis += w;
}
}
while (bfs())
{
update();
}
printf("%lld\n", ans);
return 0;
}
Dinic
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 450;
const int M = 1e5 + 50;
const int Mod = 1e9 + 7;
const int Inf = 1e9;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int t, n;
int S, T;
int a[N][N];
struct edge
{
int to, dis, nxt;
} e[N * N];
int head[N], cnt = 1;
void add_edge(int u, int v, int w)
{
++cnt;
e[cnt].to = v;
e[cnt].dis = w;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int dep[N];
int bfs()
{
memset(dep, 0, sizeof(dep));
queue<int> q;
q.push(S);
dep[S] = 1;
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 (!dep[v] && e[i].dis > 0)
{
dep[v] = dep[u] + 1;
q.push(v);
if (v == T)
return true;
}
}
}
return false;
}
int cur[N];
int dinic(int u, int sum)
{
if (u == T)
return sum;
int res = 0;
for (int i = head[u]; i && sum; i = e[i].nxt)
{
int v = e[i].to;
if (e[i].dis > 0 && dep[v] == dep[u] + 1)
{
int k = dinic(v, min(sum, e[i].dis));
if (k == 0)
dep[v] = 0;
e[i].dis -= k;
e[i ^ 1].dis += k;
sum -= k;
res += k;
}
}
return res;
}
int main()
{
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
t = read();
while (t--)
{
cnt = 1;
memset(head, 0, sizeof(head));
n = read();
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
{
a[i][j] = read();
if (!a[i][j])
continue;
add_edge(i, j + n, a[i][j]);
add_edge(j + n, i, 0);
}
}
S = n + n + 1, T = n + n + 2;
for (int i = 1; i <= n; ++i)
add_edge(S, i, 1), add_edge(i, S, 0);
for (int j = 1; j <= n; ++j)
add_edge(n + j, T, 1), add_edge(T, n + j, 0);
int flow = 0, maxflow = 0;
while (bfs())
{
while (flow = dinic(S, Inf))
maxflow += flow;
}
if (maxflow < n)
puts("No");
else
puts("Yes");
}
return 0;
}
字符串
KMP
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e6+50;
int kmp[N];
char a[N],b[N];
int la,lb;
void KMP(){
cin>>a+1;la=strlen(a+1);
cin>>b+1;lb=strlen(b+1);
int j=0;
for(int i=2;i<=lb;++i){
while(j&&b[i]!=b[j+1]) j=kmp[j];
if(b[j+1]==b[i]) ++j;
kmp[i]=j;
}
j=0;
for(int i=1;i<=la;++i){
while(j&&a[i]!=b[j+1]) j=kmp[j];
if(b[j+1]==a[i]) j++;
if(j==lb){
printf("%d\n",i-lb+1);
j=kmp[j];
}
}
for(int i=1;i<=lb;++i) printf("%d ",kmp[i]);
}
int main()
{
KMP();
return 0;
}

浙公网安备 33010602011771号