【CSP(NOIP)】主要模板

前言:

  今年最後一篇博客了TTTT
  下面都是(真)聯賽模板,太簡單或難的就不放了

一.數學問題

1.快速乘/快速冪

inline int ksc(int a,int b,int mod)
{
	int ans=0;
	a%=mod;
	while(b)
	{
	  if(b&1) ans=(ans+a)%mod;
	  b>>=1;
	  a=(a+a)%mod;
	}
	return ans;
}

inline int mul(int a,int b)//O(1)快速乘
{
    return (a*b-(int)((long double)a/mod*b)*mod+mod)%mod;
}


inline int ksm(int a,int b,int c)//a^b%c
{
	int ans=1;
	a=a%c;
	while(b)
	{
	  if(b&1) ans=ans*a%c;
	  a=(a*a)%c,b>>=1;
	}
	return ans;
}

2.Lucas定理

#include <bits/stdc++.h>
#define int long long
using namespace std;
 
const int Max=100005;
int t,n,m,mod;
int mul[Max],inv[Max];
 
inline void pre()
{
	mul[0]=inv[1]=1;
	for(int i=1;i<=mod;i++) mul[i]=(mul[i-1]*i)%mod;
	for(int i=2;i<=mod;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
 
inline int C(int n,int m)
{
	if(n>=0&&m>=0&&n>=m) return (mul[n]*inv[mul[m]]%mod*inv[mul[n-m]])%mod;
	return 0;
}
 
inline int Lucas(int n,int m)
{
	if(!m) return 1;
	return (Lucas(n/mod,m/mod)*C(n%mod,m%mod))%mod;
}
 
signed main()
{
	scanf("%d",&t);
	while(t--)
	{
	  scanf("%d%d%d",&n,&m,&mod);
	  if(n+m<m) {cout<<"0\n";continue;}
	  pre();
	  printf("%d\n",Lucas(n+m,m));
	}
	return 0;
}

3.exCRT(擴展中國剩餘定理)

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#define int long long
using namespace std;
 
const int Max=1000010;
int k,x,y,gcd;
int a[Max],m[Max];
 
inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') {f=-1;c=getchar();}
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
 
inline void exgcd(int a,int b)
{
	if(!b) x=1,y=0,gcd=a;
	else
	{
	  exgcd(b,a%b);
	  int t=x;
	  x=y;
	  y=t-a/b*x;
	}
}
 
inline int solve()
{
	int pa=a[1],pm=m[1];
	for(int i=2;i<=k;i++)
	{
	  exgcd(pm,m[i]);
	  if((a[i]-pa)%gcd) return -1;
	  x=(x*(a[i]-pa)/gcd%m[i]+m[i])%m[i];
	  pa=x*pm+pa;
	  pm=pm*m[i]/gcd;
	  pa=(pa%pm+pm)%pm;
	}
	return pa;
}
 
signed main()
{
	while(~scanf("%d",&k))
	{
	  for(int i=1;i<=k;i++) m[i]=get_int(),a[i]=get_int();
	  cout<<solve()<<"\n";
	}
	return 0;
}

4.高斯消元

#include <bits/stdc++.h>
using namespace std;

const int Max=105;
int n,l,tag;
double tmp,num[Max][Max],ans[Max];

inline void solve()
{
	for(int i=1;i<=n;i++)
	{
	  l=i;
	  for(int j=i+1;j<=n;j++) if(fabs(num[l][i])<fabs(num[j][i])) l=j;
	  for(int j=1;j<=n+1;j++) swap(num[l][j],num[i][j]);
		for(int j=i+1;j<=n;++j)
			for(int p=i+1;p<=n+1;++p)
				num[j][p]-=num[j][i]*num[i][p]/num[i][i];
	}
	int fg=0;
	for(int i=1;i<=n;++i)
	{
		fg=0;
		for(int j=i;j<=n;++j)	if(num[i][j]) fg=1;
		if(num[i][n+1]&&fg==0) {tag=1;return;}
		if(num[i][n+1]==0&&fg==0) {tag=2;return;}
	}
	for(int i=n;i;i--)
	{
	  tmp=num[i][n+1];
	  for(int j=i+1;j<=n;j++) tmp-=ans[j]*num[i][j];
	  ans[i]=tmp/num[i][i];
	}
}

int main()
{
	freopen("lx.in","r",stdin);

	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n+1;j++) scanf("%lf",&num[i][j]);
	solve();
	if(tag==1) {puts("-1");return 0;}
	if(tag==2) {puts("0");return 0;}
	for(int i=1;i<=n;i++)
	{
	  if(fabs(ans[i])<1e-8) printf("x%d=0\n",i);
	  else printf("x%d=%.2f\n",i,ans[i]);
	}
	return 0;
}

二.圖論

1.dijkstra

#include <bits/stdc++.h>
using namespace std;

const int Maxn=10005;
const int Maxm=100005;
int n,m,s,tot;
int dis[Maxn],first[Maxn],vis[Maxn];
struct shu{int to,next,len;}edge[Maxm<<1];

inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-')f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline void build(int x,int y,int z){edge[++tot].next=first[x],first[x]=tot,edge[tot].to=y,edge[tot].len=z;}
inline void init()
{
	n=get_int(),m=get_int(),s=get_int();
	memset(dis,0x3f3f3f,sizeof(dis));
	for(int i=1;i<=m;i++)
	{
	  int x=get_int(),y=get_int(),z=get_int();
	  build(x,y,z),build(y,x,z);
	}
}
inline void dijkstra()
{
	dis[s]=0;
	priority_queue<pair<int,int> >q;
	q.push(make_pair(0,s));
	while(!q.empty())
	{
	  int p=q.top().second;q.pop();
	  if(vis[p]) continue;vis[p]=1;
	  for(int u=first[p];u;u=edge[u].next)
	  {
		int to=edge[u].to;
		if(dis[to]>dis[p]+edge[u].len)
		{
		  dis[to]=dis[p]+edge[u].len;
		  q.push(make_pair(-dis[to],to));
		}
	  }
	}
	cout<<dis[n];
}

int main()
{
	init();
	dijkstra();
	return 0;
}

2.最短路計數

#include <bits/stdc++.h>
using namespace std;

const int Max=1000005;
const int mod=100003;
int n,m,s,ans[Max],dis[Max],first[Max],vis[Max];
struct shu{int to,next;}edge[Max<<2];

inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void print(int x)
{
	if(x>9) print(x/10);
	putchar('0'+x%10);
}

inline void build(int x,int y){edge[++s].next=first[x],first[x]=s,edge[s].to=y;}
inline void init()
{
	n=get_int(),m=get_int();
	for(int i=1;i<=m;i++)
	{
	  int x=get_int(),y=get_int();
	  build(x,y),build(y,x);
	}
}
inline void dijkstra()
{
	priority_queue<pair<int,int> >q;
	memset(dis,0x3f3f3f,sizeof(dis));
	ans[1]=1,dis[1]=0,q.push(make_pair(0,1));
	while(q.size())
	{
	  int p=q.top().second;q.pop();if(vis[p]) continue;vis[p]=1;
	  for(int u=first[p];u;u=edge[u].next)
	  {
	  	int to=edge[u].to;
	  	if(dis[to]==dis[p]+1) ans[to]=(ans[to]+ans[p])%mod;
	  	else if(dis[to]>dis[p]+1) dis[to]=dis[p]+1,ans[to]=ans[p],q.push(make_pair(-dis[to],to));
	  }
	}
}
inline void solve()
{
	dijkstra();
	for(int i=1;i<=n;i++)
	  if(dis[i]<=n) print(ans[i]),putchar('\n');
	  else puts("0");
}

int main()
{
	init();
	solve();
	return 0;
}

3.割點

#include <bits/stdc++.h>
using namespace std;

const int Maxn=100005;
const int Maxm=500005;
int n,m,s,Index;
int first[Maxn],vis[Maxn],num[Maxn],low[Maxn],size[Maxn];
long long ans[Maxn];
struct shu{int to,next;}e[Maxm<<1];

inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void print(long long x)
{
	if(x<0) x=-x,putchar('-');
	if(x>9) print(x/10);
	putchar('0'+x%10);
}

inline void build(int x,int y){e[++s].next=first[x],first[x]=s,e[s].to=y;}
inline void tarjan(int p)
{
	int flag=0,sum=0;
	low[p]=num[p]=++Index,size[p]=1;
	for(int u=first[p];u;u=e[u].next)
	{
	  int to=e[u].to;
	  if(!num[to])
	  {
	  	tarjan(to),low[p]=min(low[p],low[to]),size[p]+=size[to];
	  	if(low[to]>=num[p])
	  	{
	  	  flag++,ans[p]+=(long long)size[to]*(n-size[to]),sum+=size[to];
	  	  if(p!=1||flag>1) vis[p]=1;
	  	}
	  }
	  else low[p]=min(low[p],num[to]);
	}
	if(vis[p]) ans[p]+=(long long)(n-sum-1)*(sum+1)+n-1;
	else ans[p]=2*(n-1);
}

int main()
{
	n=get_int(),m=get_int();
	for(int i=1;i<=m;i++)
	{
	  int x=get_int(),y=get_int();
	  if(x==y) continue;
	  build(x,y),build(y,x);
	}
	tarjan(1);
	for(int i=1;i<=n;i++) print(ans[i]),putchar('\n');
	return 0;
}

4.tarjan強連通

#include <bits/stdc++.h>
using namespace std;

const int Maxn=10005;
const int Maxm=50005;
int n,m,s,ans1,ans2,cnt,tot,Index;
int first[Maxn],fr[Maxn],to[Maxn],fa[Maxn],q[Maxn],vis[Maxn],low[Maxn],num[Maxn];
struct shu{int to,next;}e[Maxm<<1];

inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline void build(int x,int y){e[++s].next=first[x],first[x]=s,e[s].to=y;}
inline void tarjan(int p)
{
	low[p]=num[p]=++Index;
	q[++tot]=p,vis[p]=1;
	for(int u=first[p];u;u=e[u].next)
	{
	  int to=e[u].to;
	  if(!num[to]) tarjan(to),low[p]=min(low[p],low[to]);
	  else if(vis[to]) low[p]=min(low[p],num[to]);
	}
	if(num[p]==low[p])
	{
	  cnt++;
	  while(1)
	  {
	  	int x=q[tot--];
	  	vis[x]=0,fa[x]=cnt;
	  	if(x==p) break;
	  }
	}
}

int main()
{
	freopen("lx.in","r",stdin);

	n=get_int(),m=get_int();
	for(int i=1;i<=m;i++)
	{
	  int x=get_int(),y=get_int();
	  build(x,y);
	}
	for(int i=1;i<=n;i++) if(!num[i]) tarjan(i);
	for(int i=1;i<=n;i++)
	  for(int u=first[i];u;u=e[u].next)
	    if(fa[i]!=fa[e[u].to]) fr[fa[i]]++,to[fa[e[u].to]]++;
	for(int i=1;i<=cnt;i++)
	{
	  if(!to[i]) ans1++;
	  if(!fr[i]&&to[i]) ans2++;
	}
	cout<<ans1<<"\n"<<ans1*ans2<<"\n";
	return 0;
}

5.邊雙聯通

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;

const int Max=50005;
int n,m,s=1,tot,cnt,sum,Index;
int first[Max],num[Max],low[Max],fa[Max],q[Max],to[Max];
struct shu{int to,next;}e[Max<<1];

inline int get_int()
{
	int x=0;char c;
	for(c=getchar();!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x;
}

inline void build(int x,int y)
{
	e[++s].next=first[x],first[x]=s,e[s].to=y;
	e[++s].next=first[y],first[y]=s,e[s].to=x;
}
inline void tarjan(int p,int f)
{
	num[p]=low[p]=++Index,q[++tot]=p;
	for(int u=first[p];u;u=e[u].next)
	{
  	  int to=e[u].to;
  	  if((u^1)!=f)
  	  {
  	  	if(!num[to]) tarjan(to,u),low[p]=min(low[p],low[to]);
  	  	else low[p]=min(low[p],num[p]);
  	  }
	}
	if(low[p]==num[p])
	{
	  cnt++;
	  while(1)
	  {
	  	int x=q[tot--];
	  	fa[x]=cnt;
	  	if(x==p) break;
	  }
	}
}

int main()
{
	freopen("lx.in","r",stdin);

	n=get_int(),m=get_int();
	while(m--)
	{
	  int x=get_int(),y=get_int();
	  build(x,y);
	}
	tarjan(1,0);
	for(int i=1;i<=n;i++)
	  for(int u=first[i];u;u=e[u].next)
	    if(fa[i]!=fa[e[u].to])
	      to[fa[i]]++;
	for(int i=1;i<=cnt;i++) if(to[i]==1) sum++;
	cout<<(sum+1)/2;
	return 0;
}

6.最大流

#include <bits/stdc++.h>
using namespace std;

const int inf=1e9;
const int Maxn=105;
const int Maxm=5005;
int n,m,size=1,s,t;
long long ans;
int first[Maxn],dep[Maxn],tmp[Maxn];
struct shu{int to,next,len;}e[Maxm<<1];

inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline void build(int x,int y,int z)
{
	e[++size].next=first[x],first[x]=size,e[size].to=y,e[size].len=z;
	e[++size].next=first[y],first[y]=size,e[size].to=x,e[size].len=0;
}

inline void init()
{
	n=get_int(),m=get_int(),s=get_int(),t=get_int();
	for(int i=1;i<=m;i++)
	{
	  int x=get_int(),y=get_int(),z=get_int();
	  build(x,y,z);
	}
}

inline bool bfs()
{
	queue<int>q;
	for(int i=1;i<=n;i++) dep[i]=0;
	q.push(s),dep[s]=1;
	while(q.size())
	{
	  int p=q.front();q.pop();
	  for(int u=first[p];u;u=e[u].next)
	  {
	    int to=e[u].to;
	    if(dep[to]||!e[u].len) continue;
	  	dep[to]=dep[p]+1,q.push(to);
	  	if(to==t) return 1;
	  }
	}
	return 0;
}
inline int dinic(int p,int flow)
{
	if(p==t) return flow;
	int sum=0;
	for(int &u=tmp[p];u;u=e[u].next)
	{
	  int to=e[u].to;
	  if(dep[to]!=dep[p]+1||!e[u].len) continue;
	  int minn=dinic(to,min(e[u].len,flow-sum));
	  sum+=minn,e[u].len-=minn,e[u^1].len+=minn;
	  if(sum==flow) return sum;
	}
	return dep[p]=0,sum;
}
inline void solve()
{
	while(bfs())
	{
	  for(int i=1;i<=n;i++) tmp[i]=first[i];
	  ans+=dinic(s,inf);
	}
	cout<<ans;
}

int main()
{
	init();
	solve();
	return 0;
}

7.二分圖最大匹配

#include <bits/stdc++.h>
using namespace std;

const int inf=1e9+7;
const int Maxn=2005;
const int Maxm=1005000;
int k,n,m,tot,s,t,ans;
int first[Maxn],dep[Maxn],tmp[Maxn];
struct shu{int to,next,len;}edge[Maxm<<1];

inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline void build(int x,int y,int z){edge[++tot].next=first[x],first[x]=tot,edge[tot].to=y,edge[tot].len=z;}
inline void init()
{
	n=get_int(),m=get_int(),k=get_int();
	tot=1,s=0,t=n+m+1;
	for(int i=1;i<=k;i++)
	{
	  int x=get_int(),y=get_int();
	  if(x>n||y>m) continue;
	  build(x,y+n,1),build(y+n,x,0);
	}
	for(int i=1;i<=n;i++) build(0,i,1),build(i,0,0);
	for(int i=n+1;i<=n+m;i++) build(i,t,1),build(t,i,0);
}
inline bool bfs()
{
	queue<int>q;
	for(int i=s;i<=t;i++) dep[i]=0;
	dep[s]=1,q.push(s);
	while(q.size())
	{
	  int p=q.front();q.pop();
	  for(int u=first[p];u;u=edge[u].next)
	  {
	  	int to=edge[u].to;
	  	if(dep[to]||!edge[u].len) continue;
	  	dep[to]=dep[p]+1,q.push(to);
	  	if(to==t) return 1;
	  }
	}
	return 0;
}
inline int dinic(int p,int flow)
{
	if(p==t) return flow;
	int res=flow;
	for(int &u=tmp[p];u;u=edge[u].next)
	{
	  int to=edge[u].to;
	  if(dep[to]!=dep[p]+1||!edge[u].len) continue;
	  int sum=dinic(to,min(edge[u].len,res));
	  res-=sum,edge[u].len-=sum,edge[u^1].len+=sum;
	  if(!res) return flow;
	}
	return flow-res;
}
inline void solve()
{
	while(bfs())
	{
	  for(int i=0;i<=t;i++) tmp[i]=first[i];
	  ans+=dinic(s,inf);
	}
	cout<<ans;
}

int main()
{
 	freopen("lx.in","r",stdin);

	init();
	solve();
	return 0;
}

8.SPFA判負環

#include <bits/stdc++.h>
#define Max 2010
using namespace std;
 
int n,m,t,s;
int first[Max],cnt[Max],dis[Max],vis[Max];
struct shu{int to,next,len;};
shu edge[6010];
queue<int>q;
 
inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') {f=-1;c=getchar();}
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
 
inline void build(int x,int y,int z)
{
	edge[++s].next=first[x];
	first[x]=s;
	edge[s].to=y;
	edge[s].len=z;
}
 
inline int SPFA()
{
	while(!q.empty()) q.pop();
	dis[1] = 0,cnt[1] = 1;
	q.push(1);
	while(!q.empty())
	{
	  int point = q.front();
	  q.pop();
	  vis[point] = 0;
	  for(register int u=first[point];u;u=edge[u].next)
	  {
		int to=edge[u].to;
		if(dis[to] > dis[point] + edge[u].len)
		{
		  dis[to] = dis[point] + edge[u].len;
		  if(!vis[to])
		  {
		  	cnt[to] = cnt[to] + 1;
		    if(cnt[to] >= n) return 1; 
			vis[to] = 1;
			q.push(to);
		  }
		}
	  }
	}
	return 0;
}
 
int main()
{
	t=get_int();
	while(t--)
	{
	  s=0;
	  n=get_int(),m=get_int();
	  for(register int i=1;i<=n;++i) vis[i] = cnt[i] = first[i] = 0,dis[i] = 1e9;
	  for(register int i=1;i<=m;++i)
	  {
	    int x=get_int(),y=get_int(),z=get_int();
	    build(x,y,z);
	    if(z >= 0) build(y,x,z);
	  }
	  SPFA() ? printf("YE5\n") : printf("N0\n");
	}
}

9.樹的直徑

#include <bits/stdc++.h>
using namespace std;
 
const int Max=100010;
int n,m,size,ans;
int first[Max],f[Max],d[Max];
struct shu{int to,next,len;}edge[Max<<1];
 
inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
 
inline void build(int x,int y,int z){edge[++size].next=first[x],first[x]=size,edge[size].to=y,edge[size].len=z;}
inline void dfs(int p,int fa)
{
	for(int u=first[p];u;u=edge[u].next)
	{
	  int to=edge[u].to;
	  if(to==fa) continue;
	  dfs(to,p);
	  f[p]=max(f[p],d[p]+edge[u].len+d[to]);
	  d[p]=max(d[p],edge[u].len+d[to]);
	}
}
 
int main()
{
	n=get_int();
	for(int i=1;i<n;i++)
	{
	  int x=get_int(),y=get_int(),z=get_int();
	  build(x,y,z),build(y,x,z);
	}
	dfs(1,0);
	for(int i=1;i<=n;i++) ans=max(ans,f[i]);
	cout<<ans;
	return 0;
}

10.樹的重心

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;

const int Max=20005;
int n,m,t,s,id,ans;
int first[Max],size[Max];
struct shu{int to,next;}edge[Max<<1];

inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='0');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}

inline void build(int x,int y){edge[++s].next=first[x],first[x]=s,edge[s].to=y;}
inline void init()
{
	n=get_int(),s=0,id=ans=1e9;
	for(int i=1;i<=n;i++) size[i]=first[i]=0;
	for(int i=1;i<n;i++)
	{
	  int x=get_int(),y=get_int();
	  build(x,y),build(y,x);
	}
}
inline void dfs(int p,int fa)
{
	size[p]=1;int mx=0;
	for(int u=first[p];u;u=edge[u].next)
	{
	  int to=edge[u].to;
	  if(to==fa) continue;
	  dfs(to,p),size[p]+=size[to],mx=max(mx,size[to]);
	}
	mx=max(mx,n-size[p]);
	if(ans>mx) ans=mx,id=p;
	else if(ans==mx) id=min(id,p);
}
inline void solve()
{
	dfs(1,0);
	cout<<id<<" "<<ans<<"\n";
}

int main()
{
	t=get_int();
	while(t--)
	{
	  init();
	  solve();
	}
	return 0;
}

11.樹剖求LCA

inline void dfs1(int p)
{
	size[p]=vis[p]=1;
	for(int u=first[p];u;u=edge[u].next)
	{
	  int to=edge[u].to;
	  if(vis[to]) continue;
	  fa[to]=p,dep[to]=dep[p]+1,dfs1(to),size[p]+=size[to];
	  if(size[son[p]]<size[to]) son[p]=to;
	}
}
inline void dfs2(int p,int tp)
{
	top[p]=tp;
	if(!son[p]) return;
	dfs2(son[p],tp);
	for(int u=first[p];u;u=edge[u].next)
	{
	  int to=edge[u].to;
	  if(to==fa[p]||to==son[p]) continue;
	  dfs2(to,to);
	}
}
inline 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]];
	}
	return dep[x]<dep[y] ? x : y;
}

12.樹鏈剖分

#include <bits/stdc++.h>
using namespace std;

const int Max=30005;
int n,m,tot,s;
int first[Max],num[Max];
int tree[Max<<2],sum[Max<<2];
int top[Max],dep[Max],son[Max],size[Max],fa[Max],rev[Max],seg[Max];
struct shu{int to,next;}e[Max<<1];
////////////////////////////////////////////
inline int get_int()
{
	int x=0,f=1;char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void print(int x)
{
	if(x<0) x=-x,putchar('-');
	if(x>9) print(x/10);
	putchar('0'+x%10);
}
inline int max(int a,int b){return a<b?b:a;}
////////////////////////////////////////////
inline void build(int x,int y)
{
	e[++s].next=first[x],first[x]=s,e[s].to=y;
	e[++s].next=first[y],first[y]=s,e[s].to=x;
}
inline void dfs1(int p)
{
	size[p]=1;
	for(int u=first[p];u;u=e[u].next)
	{
	  int to=e[u].to;
	  if(to==fa[p]) continue;
	  fa[to]=p,dep[to]=dep[p]+1,dfs1(to),size[p]+=size[to];
	  if(size[to]>size[son[p]]) son[p]=to;
	}
}
inline void dfs2(int p,int tp)
{
	top[p]=tp,seg[rev[p]=++tot]=p;
	if(!son[p]) return;
	dfs2(son[p],tp);
	for(int u=first[p];u;u=e[u].next)
	{
	  int to=e[u].to;
	  if(to==fa[p]||to==son[p]) continue;
	  dfs2(to,to);
	}
}
////////////////////////////////////////////
inline void update(int rt){tree[rt]=max(tree[rt<<1],tree[rt<<1|1]),sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
inline void buildtree(int rt,int l,int r)
{
	if(l==r){tree[rt]=sum[rt]=num[seg[l]];return;}
	int mid=(l+r)>>1;
	buildtree(rt<<1,l,mid),buildtree(rt<<1|1,mid+1,r);
	update(rt);
}
inline void modify(int rt,int l,int r,int pos,int x)
{
	if(l==r){tree[rt]=sum[rt]=x;return;}
	int mid=(l+r)>>1;
	if(pos<=mid) modify(rt<<1,l,mid,pos,x);
	else modify(rt<<1|1,mid+1,r,pos,x);
	update(rt);
}
inline int Qmax(int rt,int l,int r,int L,int R)
{
	if(L<=l&&R>=r) return tree[rt];
	int mid=(l+r)>>1,ans=-1e9;
	if(L<=mid) ans=max(ans,Qmax(rt<<1,l,mid,L,R));
	if(R>mid) ans=max(ans,Qmax(rt<<1|1,mid+1,r,L,R));
	return ans;
}
inline int Qsum(int rt,int l,int r,int L,int R)
{
	if(L<=l&&R>=r) return sum[rt];
	int mid=(l+r)>>1,ans=0;
	if(L<=mid) ans+=Qsum(rt<<1,l,mid,L,R);
	if(R>mid) ans+=Qsum(rt<<1|1,mid+1,r,L,R);
	return ans;
}
////////////////////////////////////////////
inline int ask(int x,int y,int tag)
{
	int ans=(tag==1)?-1e9:0;
	while(top[x]!=top[y])
	{
	  if(dep[top[x]]<dep[top[y]]) swap(x,y);
	  if(tag==1) ans=max(ans,Qmax(1,1,tot,rev[top[x]],rev[x]));
	  else ans+=Qsum(1,1,tot,rev[top[x]],rev[x]);
	  x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	if(tag==1) ans=max(ans,Qmax(1,1,tot,rev[x],rev[y]));
	else ans+=Qsum(1,1,tot,rev[x],rev[y]);
	return ans;
}
////////////////////////////////////////////
int main()
{
	freopen("lx.in","r",stdin);

	n=get_int();
	for(int i=1;i<n;i++)
	{
	  int x=get_int(),y=get_int();
	  build(x,y);
	}
	for(int i=1;i<=n;i++) num[i]=get_int();
	dfs1(1),dfs2(1,1),buildtree(1,1,tot);
	m=get_int();
	while(m--)
	{
	  char ch[10];scanf("%s",ch);int x=get_int(),y=get_int();
	  if(ch[1]=='H') modify(1,1,tot,rev[x],y);
	  else if(ch[1]=='M') print(ask(x,y,1)),putchar('\n');
	  else print(ask(x,y,2)),putchar('\n');
	}
	return 0;
}

三.字符串

1.KMP

#include <bits/stdc++.h>
using namespace std;

const int Max=1000005;
int n,m,tag,first[Max];
char a[Max],b[Max];

inline void init()
{
	scanf("%s\n%s",a+1,b+1);
	n=strlen(a+1),m=strlen(b+1);
}
inline void pre()
{
	for(int i=2,j=0;i<=m;i++)
	{
	  while(b[i]!=b[j+1]&&j) j=first[j];
	  if(b[i]==b[j+1]) j++;first[i]=j;
	}
}
inline void solve()
{
	for(int i=1,j=0;i<=n;i++)
	{
	  while(j&&a[i]!=b[j+1]) j=first[j];
	  if(a[i]==b[j+1]) j++;
	  if(j==m) tag=1,cout<<i-m+1<<"\n";
	}
	if(!tag) puts("NO");
}

int main()
{
	init();
	pre();
	solve();
	return 0;
}

2.字符串哈希

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
using namespace std;
 
const int Max=1000005;
int n,m,tag,t;
unsigned long long Pow[Max],hash1[Max],hash2[Max];
char  ch1[Max],ch2[Max];

const void solve()
{
	Pow[0]=1,tag=0;
	for(int i=1;i<=m;i++) hash2[i]=hash2[i-1]*131+ch2[i]-'a',Pow[i]=Pow[i-1]*131;
	for(int i=1;i<=n;i++)
	{
	  hash1[i]=hash1[i-1]*131+ch1[i]-'a';
	  if(i>=m&&hash1[i]==hash1[i-m]*Pow[m]+hash2[m]) tag=1,cout<<i-m+1<<"\n";
	}
}
 
int main()
{
	scanf("%s",ch1+1);
	n=strlen(ch1+1); 
	scanf("%s",ch2+1);
	m=strlen(ch2+1);
	solve();
	if(!tag) puts("NO");
	return 0;
}

四.數據結構

1.RMQ

#include <bits/stdc++.h>
using namespace std;
 
const int Max=50005;
int n,m;
int f[Max][18],g[Max][18],Log[Max];
inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') f=-1,c=getchar();
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
inline void print(int x)
{
	if(x>9) print(x/10);
	putchar('0'+x%10);
}
inline int mx(int x,int y){return x < y ? y : x;}
inline int mn(int x,int y){return x < y ? x : y;}
inline void pre()
{
	Log[0]=-1;
	for(int i=1;i<=n;i++) Log[i]=Log[i>>1]+1;
	for(int j=1;(1<<j)<=n;j++)
	  for(int i=1;i+(1<<j)-1<=n;i++)
	    f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]),g[i][j]=min(g[i][j-1],g[i+(1<<j-1)][j-1]);
}
 
int main()
{
	n=get_int(),m=get_int();
	for(int i=1;i<=n;i++) g[i][0]=f[i][0]=get_int();
	pre();
	while(m--)
	{
	  int x=get_int(),y=get_int(),len=Log[y-x+1];
	  print(mx(f[x][len],f[y-(1<<len)+1][len])-mn(g[x][len],g[y-(1<<len)+1][len])),putchar('\n');
	}
	return 0;
}

2.線段樹

  線段樹的模板實在是太多了,如果考到應該不會太複雜,所以就略過了。

3.主席樹

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
using namespace std;
 
const int Max=100010;
int n,m,q,s;
int num[Max],a[Max],sum[Max*20],lc[Max*20],rc[Max*20],root[Max*20];
 
inline int get_int()
{
	int x=0,f=1;
	char c;
	for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
	if(c=='-') {f=-1;c=getchar();}
	for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
	return x*f;
}
 
inline void pre()
{
	sort(a+1,a+n+1);
	m=unique(a+1,a+n+1)-a-1;
	for(int i=1;i<=n;i++) num[i] = lower_bound(a+1,a+m+1,num[i]) - a;
}
 
inline void build(int fa,int &now,int l,int r,int num)
{
	now = ++s;
	sum[now] = sum[fa] + 1;
	lc[now] = lc[fa],rc[now] = rc[fa];
	if(l==r) return;
	int mid = l + r >> 1;
	if(num <= mid) build(lc[fa],lc[now],l,mid,num);
	else build(rc[fa],rc[now],mid+1,r,num);
}
 
inline int Q(int root1,int root2,int l,int r,int k)
{
	if(l==r) return l;
	int mid = l + r >> 1,num = sum[lc[root1]] - sum[lc[root2]];
	if(num >= k) return Q(lc[root1],lc[root2],l,mid,k);
	else return Q(rc[root1],rc[root2],mid+1,r,k-num);
	
}
 
inline void print(int x)
{
	if(x < 0) putchar('-'),x=-x;
	if(x > 9) print(x/10);
	putchar('0' + x % 10);
}
 
int main()
{
	n=get_int(),q=get_int();
	for(int i=1;i<=n;i++) num[i] = a[i] = get_int();
	pre();
	for(int i=1;i<=n;i++) build(root[i-1],root[i],1,m,num[i]);
	while(q--)
	{
	  int l=get_int(),r=get_int(),k=get_int();
	  print(a[Q(root[r],root[l-1],1,m,k)]),putchar('\n');
	}
 
	return 0;
}

五.動態規劃

  我覺得DPDP是沒有所謂模板的。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章