模板集合库

博客园同步

这里的所有题目,均来源于 洛谷.

一些没有 阐明主要思想 的,博主会慢慢更的。

主要功能是 供博主快速查询板子,给大家提供一个优质的模板库。

P3367 【模板】并查集

简要题意:维护连通块的合并与查询。

数据结构:并查集。

时间复杂度: O ( n ) \mathcal{O}(n) O(n).

struct BIT {
	const int N=2e5+1;
	int f[N];
	inline int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}

	inline void ins(int x,int y) { //合并操作
		f[find(x)]=find(y);
	}

	inline bool ask(int x,int y) { //查询操作
	 	return find(x) == find(y);
	}
}

P1226 【模板】快速幂||取余运算

简要题意:求 x y m o d    p x^y \mod p xymodp.

板子。

时间复杂度: O ( log ⁡ p ) O(\log p) O(logp).

typedef long long ll;
inline ll pw(ll x,ll y,ll MOD) {
	ll ans=1; while(y) {
		if(y&1) ans=ans*x%MOD;
		x=x*x%MOD; y>>=1;
	} 
}

P3371 【模板】单源最短路径(弱化版)

简要题意:给定一个图,求 s s s 到各点的最短路。

算法: SPFA \text{SPFA} SPFA.

时间复杂度: O ( n 2 ) O(n^2) O(n2).

const int N=2e5+1;
int n,m,s,dis[N];
vector<pair<int,int> >G[N];
bool vis[N];

inline void SPFA() {
	queue<int>q; memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++) dis[i]=INT_MAX;
	q.push(s); dis[s]=0; vis[s]=1;
	while(!q.empty()) {
		int u=q.front();
		q.pop(); vis[u]=0;
		for(int i=0;i<G[u].size();i++) {
			int v=G[u][i].first,z=G[u][i].second;
			if(dis[v]>dis[u]+z) {
				dis[v]=dis[u]+z;
				if(!vis[v]) {vis[v]=1; q.push(v);}
			}
		}
	}
}

P4779 【模板】单源最短路径(标准版)

简要题意:同弱化版。

算法: Dijkstra \text{Dijkstra} Dijkstra + 堆优化。

时间复杂度: O ( n log ⁡ n ) \mathcal{O}(n \log n) O(nlogn).

const int N=2e5+1;
int n,m,s,dis[N]; bool vis[N]; vector<pair<int,int> > G[N];
priority_queue<pair<int,int> , vector<pair<int,int> > , greater<pair<int,int> > > q;

inline void Dijkstra(int s) {
	dis[s]=0; q.push(make_pair(0,s));
	while(!q.empty()) {
		int x=q.top().second; q.pop();
		if(vis[x]) continue; vis[x]=1;
		for(int i=0;i<G[x].size();i++) {
			int y=G[x][i].first,w=G[x][i].second;
			if(dis[x]+w<dis[y]) {
				dis[y]=dis[x]+w;
				if(!vis[y]) q.push(make_pair(dis[y],y));
			}
		}
	}
}

P3383 【模板】线性筛素数

注:这题经过一次变换。

简要题意:若干查询第 k k k 小素数。

板子。

时间复杂度: O ( n ) O(n) O(n).

const int N=1e8+1;
const int SN=1e6+1;
bool h[N]; int cnt=0;
int n,m,prime[SN];

inline void Euler() {
	for(int i=2;i<=n;i++) {
		if(!h[i]) prime[++cnt]=i;
		for(int j=1;j<=cnt && i*prime[j]<=n;j++) {
			h[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		}
	}	
}

P3366 【模板】最小生成树

简要题意:求 最小生成树

算法: kruskal \text{kruskal} kruskal.

时间复杂度: O ( n m + m log ⁡ m ) \mathcal{O}(nm + m \log m) O(nm+mlogm).

const int N=2e5+1;
struct tree{
    int start,end;
    int len;
} a[N];
int n,m,s=0,p=0;
bool h[N],vis[N];
vector<pair<int,int> >G[N];
 
inline bool cmp(tree x,tree y){return x.len<y.len;}

inline void dfs(int dep) {
	if(vis[dep]) return;
	vis[dep]=1; p++;
	for(int i=0;i<G[dep].size();i++) dfs(G[dep][i].first);
}

inline bool check(){
	dfs(1);
	if(p==n) return 0;
	return 1;
}
 
int main(){
    n=read(),m=read();
    for(int i=1;i<=m;i++) {
        a[i].start=read(); a[i].end=read();
        a[i].len=read();
        G[a[i].start].push_back(make_pair(a[i].end,a[i].len));
    }
    if(check()) {printf("orz\n");return 0;}
    sort(a+1,a+1+m,cmp);
    s=a[1].len; h[a[1].start]=h[a[1].end]=1;
    for(int p=2;p<n;p++)
    for(int i=2;i<=m;i++)
        if(h[a[i].start]+h[a[i].end]==1) {
            s+=a[i].len;
            h[a[i].start]=h[a[i].end]=1;
            break;
        }
    printf("%d\n",s);   
    return 0;
}

P1886 滑动窗口 /【模板】单调队列

简要题意:维护滑动窗口内的极值。

算法:线段树 单调队列优化。

时间复杂度: O ( n ) \mathcal{O}(n) O(n).

const int N=2e5+1;
int n,a[N];
deque<int> q;
for(int i=1;i<=n;i++) {
		while(!q.empty() && a[q.back()]>=a[i]) q.pop_back();
		q.push_back(i);
		while(!q.empty() && q.front()+k<=i) q.pop_front();
		if(i>=k) write(a[q.front()]),putchar(' ');
	} puts(""); q.clear();
	for(int i=1;i<=n;i++) {
		while(!q.empty() && a[q.back()]<=a[i]) q.pop_back();
		q.push_back(i);
		while(!q.empty() && q.front()+k<=i) q.pop_front();
		if(i>=k) write(a[q.front()]),putchar(' ');
	} 

P3374 【模板】树状数组 1

简要题意:维护树状数组。

数据结构:树状数组。

时间复杂度: O ( n log ⁡ n + m log ⁡ n ) \mathcal{O}(n \log n + m \log n) O(nlogn+mlogn).

typedef long long ll;
const int N=1e6+1;
ll a[N],c[N];
struct BIT {
	inline int lowbit(int x) {return x & (-x);}
	inline ll sum(int x) {
		ll s=0; while(x>0) {
			s+=c[x];
			x-=lowbit(x);
		} return s;
	}

	inline void update(int x,int k) {
		a[x]+=k; while(x<=n) {
			c[x]+=k; x+=lowbit(x); 
		}
	}	
	
	inline ll query(int l,int r) {
		return sum(r)-sum(x-1);
	}
} ;

P3811 【模板】乘法逆元

简要题意:维护 1 1 1 ~ n n n 所有数关于质数 p p p 的逆元。

算法:公式递推。

时间复杂度: O ( n ) \mathcal{O}(n) O(n).

const int N=2e6+1;
int inv[N],n,MOD;
inv[1]=1;
for(int i=2;i<=n;i++) inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;

P3379 【模板】最近公共祖先(LCA)

简要题意:给定一棵树,维护最近公共祖先。

算法:倍增。

时间复杂度: O ( n log ⁡ n + m log ⁡ n ) \mathcal{O}(n \log n + m \log n) O(nlogn+mlogn).

const int N=5e5+1;
int n,m,root,fa[N];
vector<int> G[N];
int f[N][21],dep[N];

inline void dfs(int u,int fa) {
	dep[u]=dep[fa]+1; f[u][0]=fa;
	for(int i=1;i<=20;i++) f[u][i]=f[f[u][i-1]][i-1];
	for(int i=0;i<G[u].size();i++) {
		int v=G[u][i]; if(v==fa) continue;
		dfs(v,u);
	}
}

inline int LCA(int x,int y) {
	if(dep[x]>dep[y]) swap(x,y);
	for(int i=20;i>=0;i--)
		if(dep[x]<=dep[y]-(1<<i)) y=f[y][i];
	if(x==y) return x;
	for(int i=20;i>=0;i--) {
		if(f[x][i]==f[y][i]) continue;
		else x=f[x][i],y=f[y][i];
	} return f[x][0];
}

P3368 【模板】树状数组 2

简要题意:维护区间加,单点查。

数据结构:树状数组。

时间复杂度: O ( n log ⁡ n + m log ⁡ n ) \mathcal{O}(n \log n + m \log n) O(nlogn+mlogn).

随便 树状数组 维护一下就行了呗。

const int N=1e6+1;
typedef long long ll;

int a[N]; ll c[N];
int n,m,x,y;

struct BIT {
	inline int lowbit(int x) {return x & (-x);}
	inline ll sum(int x) { 
		ll s=0; while(x>0) {
			s+=c[x];
			x-=lowbit(x);
		} return s;
	}

	inline void update(int x,int k) {
		while(x<=n) {
			c[x]+=k;
			x+=lowbit(x); 
		}
	}
} ;

P3372 【模板】线段树 1

简要题意:维护线段树。

数据结构:线段树。

时间复杂度: O ( n log ⁡ n + m log ⁡ n ) \mathcal{O}(n \log n + m \log n) O(nlogn+mlogn).

#define int long long
const int N=1e5+1;
#define L (i<<1)
#define R (i<<1)+1
struct BIT {
	inline void update(int x) {
		t[x].sum=t[L].sum+t[R].sum;	
	}
	inline void build_tree(int x,int l,int r) {
		t[x].l=l; t[x].r=r; t[x].tag=0;
		if(l==r) {t[x].sum=a[l]; return;}
		int mid=(l+r)>>1;
		build_tree(L,l,mid); build_tree(R,mid+1,r);
		update(x);
	}
	inline void pushdown(int x) {
		int p=t[x].tag; if(!p) return;
		t[L].tag+=p; t[R].tag+=p;
		t[L].sum+=p*(t[L].r-t[L].l+1);
		t[R].sum+=p*(t[R].r-t[R].l+1);
		t[x].tag=0;
	}
	inline void change(int x,int l,int r,int k) {
		if(l<=t[x].l && t[x].r<=r) {t[x].tag+=k; t[x].sum+=k*(t[x].r-t[x].l+1);return;}
		int mid=(t[x].l+t[x].r)>>1; pushdown(x);
		if(l<=mid) change(L,l,r,k);
		if(r>mid) change(R,l,r,k);
		update(x);
	}
	inline int ask(int x,int l,int r) {
		if(l<=t[x].l && t[x].r<=r) return t[x].sum;
		int mid=(t[x].l+t[x].r)>>1,ans=0; pushdown(x);
		if(l<=mid) ans+=ask(L,l,r);
		if(r>mid) ans+=ask(R,l,r);
		return ans;
	}
} T;

P3373 【模板】线段树 2

简要题意:维护线段树。

数据结构:线段树。

时间复杂度: O ( n log ⁡ n + m log ⁡ n ) \mathcal{O}(n \log n + m \log n) O(nlogn+mlogn).

#define L (i<<1)
#define R (i<<1)+1
typedef long long ll;
const ll N=1e5+1;
ll n,m,MOD;

struct node{
	ll l,r,sum;
	ll mul,add;
};
node t[4*N]; ll a[N];

struct BIT {
	inline void update(ll i) {t[i].sum=(t[L].sum+t[R].sum)%MOD;}
	inline void build_tree(ll i,ll l,ll r) {
		t[i].l=l; t[i].r=r; t[i].mul=1;
		if(l==r) {t[i].sum=a[l]%MOD;return;}
		ll mid=(l+r)>>1;
		build_tree(L,l,mid);
		build_tree(R,mid+1,r);
		update(i);
	}

	inline void pushdown(ll i) {
		t[L].sum=(t[i].mul*t[L].sum+((t[L].r-t[L].l+1)*t[i].add)%MOD)%MOD;
		t[R].sum=(t[i].mul*t[R].sum+((t[R].r-t[R].l+1)*t[i].add)%MOD)%MOD;
		t[L].mul=(t[L].mul*t[i].mul)%MOD;
		t[R].mul=(t[R].mul*t[i].mul)%MOD;
		t[L].add=(t[i].mul*t[L].add+t[i].add)%MOD;
		t[R].add=(t[i].mul*t[R].add+t[i].add)%MOD;
		t[i].mul=1; t[i].add=0;
	}

	inline void change_add(ll i,ll l,ll r,ll k) {
		if(l<=t[i].l && t[i].r<=r) {
			t[i].add=(t[i].add+k)%MOD;
			t[i].sum=(t[i].sum+k*(t[i].r-t[i].l+1))%MOD;
			return; 
		} pushdown(i); update(i); 
		ll mid=(t[i].l+t[i].r)>>1;
		if(l<=mid) change_add(L,l,r,k);
		if(r>mid)  change_add(R,l,r,k);
		update(i); 
	}

	inline void change_mul(ll i,ll l,ll r,ll k) {
		if(l<=t[i].l && t[i].r<=r) {
			t[i].add=(t[i].add*k)%MOD;
			t[i].mul=(t[i].mul*k)%MOD;
			t[i].sum=(t[i].sum*k)%MOD; return;
		} pushdown(i); update(i);
		ll mid=(t[i].l+t[i].r)>>1;
		if(l<=mid) change_mul(L,l,r,k);
		if(r>mid)  change_mul(R,l,r,k);
		update(i);
	}

	inline ll querysum(ll i,ll l,ll r) {
		if(l<=t[i].l && t[i].r<=r) return t[i].sum;
		pushdown(i);
		ll mid=(t[i].l+t[i].r)>>1,ans=0;
		if(l<=mid) ans=(ans+querysum(L,l,r))%MOD;
		if(r>mid)  ans=(ans+querysum(R,l,r))%MOD;
		return ans; 
	}
} ;

P3375 【模板】KMP字符串匹配

简要题意:维护 KMP \text{KMP} KMP.

算法: KMP \text{KMP} KMP.

时间复杂度: O ( n + m ) \mathcal{O}(n+m) O(n+m).

const int N=1e6+1;
char s[N],p[N];
int nxt[N];

inline void getNext() {
	nxt[0]=-1; int len=strlen(p);
	int j=0,k=-1;
	while(j<len) 
		if(k==-1 || p[j]==p[k]) {
			nxt[++j]=++k;
		} else k=nxt[k];
}

inline int KMP() {
	int i=0,j=0;
	int l1=strlen(s),l2=strlen(p);
	while(i<l1) {
		if(j==-1 || s[i]==p[j]) i++,j++;
		else j=nxt[j];
		if(j==l2) printf("%d\n",i-l2+1),j=nxt[j];
	}
	if(j==strlen(p)) return i-j;
	else return -1;
}

P1939 【模板】矩阵加速(数列)

利用矩阵加速转移, O ( log ⁡ n ) \mathcal{O}(\log n) O(logn).

typedef long long ll;
const ll MOD=1e9+7;

struct martix {
	ll a[4][4];
} s;
int n,T;

inline martix times(martix x,martix y) {
    martix t; memset(t.a,0,sizeof(t.a));
	for(int i=1;i<=3;i++) for(int j=1;j<=3;j++)
	for(int k=1;k<=3;k++)
		t.a[i][j]=(t.a[i][j]+x.a[i][k]*y.a[k][j])%MOD;
	return t;	
}

inline martix pw(martix x,int n) {
	if(n<=1) return x;
	martix ans=x; n--;
	while(n>0) {
		if(n&1) ans=times(ans,x);
		n>>=1; x=times(x,x);
	} return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值