模板

数学

乘法逆元

递推求乘法逆元

#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;
}
posted @ 2022-07-30 15:20  RVG  阅读(25)  评论(0)    收藏  举报