CSP-S考前默板

线段树

https://www.luogu.com.cn/problem/P3373

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4e5+77;
ll tr[N],ch[N],jia[N],a[N];
int n,m,mod;
void update(int u)
{
	tr[u]=(tr[u<<1]+tr[u<<1|1])%mod;
}
void pushdown(int u,int st,int ed)
{
	int mid=st+ed>>1;
	if(ch[u]!=1)
	{
		(tr[u<<1]*=ch[u])%=mod; (tr[u<<1|1]*=ch[u])%=mod; 
		(ch[u<<1]*=ch[u])%=mod; (ch[u<<1|1]*=ch[u])%=mod; (jia[u<<1]*=ch[u])%=mod; (jia[u<<1|1]*=ch[u])%=mod; 
		ch[u]=1;
	}
	if(jia[u]!=0)
	{
		(tr[u<<1]+=(mid-st+1)*jia[u])%=mod; (tr[u<<1|1]+=(ed-mid)*jia[u])%=mod; (jia[u<<1]+=jia[u])%=mod,(jia[u<<1|1]+=jia[u])%=mod,jia[u]=0;
	}
}
void build(int u,int st,int ed)
{
	if(st==ed)
	{
		tr[u]=a[st]; return;
	}
	ch[u]=1;
	int mid=st+ed>>1;
	build(u<<1,st,mid); build(u<<1|1,mid+1,ed);
	update(u);
}
void mul(int u,int st,int ed,int l,int r,int t)
{
	if(l<=st&&ed<=r)
	{
		(tr[u]*=t)%=mod; (jia[u]*=t)%=mod; (ch[u]*=t)%=mod; return;
	}
	pushdown(u,st,ed);
	int mid=st+ed>>1;
	if(l<=mid) mul(u<<1,st,mid,l,r,t);
	if(r>mid) mul(u<<1|1,mid+1,ed,l,r,t);
	update(u);
}
void add(int u,int st,int ed,int l,int r,int t)
{
	if(l<=st&&ed<=r)
	{
		(tr[u]+=t*(ed-st+1)%mod)%=mod; (jia[u]+=t)%=mod; return;
	}
	pushdown(u,st,ed);
	int mid=st+ed>>1;
	if(l<=mid) add(u<<1,st,mid,l,r,t);
	if(r>mid) add(u<<1|1,mid+1,ed,l,r,t);
	update(u);
}
ll query(int u,int st,int ed,int l,int r)
{
	if(l<=st&&ed<=r)
	{
		return tr[u];
	}
	pushdown(u,st,ed);
	int mid=st+ed>>1,ret=0;
	if(l<=mid) (ret+=query(u<<1,st,mid,l,r))%=mod;
	if(r>mid) (ret+=query(u<<1|1,mid+1,ed,l,r))%=mod;
	return ret;
}
int main()
{
	scanf("%d%d%d",&n,&m,&mod);
	for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
	build(1,1,n);
	while(m--)
	{
		int op,x,y;
		scanf("%d%d%d",&op,&x,&y);
		if(op==1)
		{
			int t;
			scanf("%d",&t);
			mul(1,1,n,x,y,t);
		}
		else if(op==2)
		{
			int t;
			scanf("%d",&t);
			add(1,1,n,x,y,t);
		}
		else
		{
			printf("%lld\n",query(1,1,n,x,y));
		}
	}
}

树状数组

https://www.luogu.com.cn/problem/P3373

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+77;
int n,m,tr[N];
void ins(int x,int t)
{
	for(int i=x; i<=n; i+=i&-i) tr[i]+=t;
}
int query(int x)
{
	int ret=0;
	for(int i=x; i; i-=i&-i) ret+=tr[i];
	return ret;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,x; i<=n; i++) scanf("%d",&x),ins(i,x);
	while(m--)
	{
		int op,x,y;
		scanf("%d%d%d",&op,&x,&y);
		if(op==1) ins(x,y);else printf("%d\n",query(y)-query(x-1));
	}
}

dijkstra

https://www.luogu.com.cn/problem/P4779

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+77;
int d[N],ls[N],n,m,s,b[N],cnt;
struct E
{
	int to,next,v;
}e[N<<1];
void add(int u,int v,int val)
{
	e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt; e[cnt].v=val;
}
struct node
{
	int id,v;
	friend bool operator < (node x,node y)
	{
		return x.v>y.v;
	}
};
void dij()
{
	memset(d,0x3f,sizeof(d));
	d[s]=0;
	priority_queue<node> q; q.push((node){s,0});
	while(!q.empty())
	{
		node p=q.top(); q.pop();
		int u=p.id; 
		if(b[u]) continue;//这个一定要在外面判 
		b[u]=1;
		for(int i=ls[u]; i; i=e[i].next)
		{
			int v=e[i].to; if(b[v]) continue;
			if(d[u]+e[i].v<d[v])
			{
				d[v]=d[u]+e[i].v; q.push((node){v,d[v]});
			}
		}
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1,x,y,z; i<=m; i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z);
	dij();
	for(int i=1; i<=n; i++) printf("%d ",d[i]);
}

三分

https://www.luogu.com.cn/problem/P3382

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;
const int N=20;
double a[N],l,r;
int n;
double F(double x)
{
	double yjy=0;
	for(int i=0; i<=n; i++) yjy=yjy*x+a[i];
	return yjy;
}
int main()
{
	scanf("%d%lf%lf",&n,&l,&r);
	for(int i=0; i<=n; i++) scanf("%lf",&a[i]);
	while(r-l>=eps)
	{
		double mid=(l+r)/2;
		if(F(mid+eps)>F(mid-eps)) l=mid;else r=mid;
	}
	printf("%.5lf",r);
}

矩阵树定理

https://www.luogu.com.cn/problem/P4111

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=207,mod=1000000000;

int n,m,tot;
ll f[N][N],Map[N][N];
int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * k;
}
void add(int u,int v)
{
	if(u>v) return;
	f[u][u]++,f[v][v]++,f[u][v]--,f[v][u]--;
}
ll Gauss()
{
	ll ans=1;
	for(int i=1; i<tot; i++)
	{
		for(int j=i+1; j<tot; j++) while(f[j][i])
		{
			ll t=f[i][i]/f[j][i];
			for(int k=i; k<tot; k++) f[i][k]=(f[i][k]-t*f[j][k]+mod)%mod;
			swap(f[i],f[j]);
			ans=-ans;
		}
		ans=(ans*f[i][i])%mod;
	}
	return ans;
}
int main()
{
	n=read(),m=read();
	for(int i = 1; i <= n; i ++)
	{
		char c;
		for(int j = 1; j <= m; j ++)
		{
			cin >> c;
			if(c == '.') Map[i][j] = ++ tot;
		}
	}
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= m; j ++)
		{
			int tem, u;
			if(!(u = Map[i][j])) continue;
			if(tem = Map[i - 1][j]) add(u, tem);
			if(tem = Map[i + 1][j]) add(u, tem);
			if(tem = Map[i][j - 1]) add(u, tem);
			if(tem = Map[i][j + 1]) add(u, tem);
		}
	printf("%lld", (Gauss()+mod)%mod);
}

树链剖分求LCA

https://www.luogu.com.cn/problem/solution/P3379

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+77;
int dep[N],fa[N],n,m,root,top[N],ls[N],cnt,id[N],son[N],siz[N],dfn[N],tot;
struct E
{
	int to,next;
}e[N<<1];
void add(int u,int v)
{
	e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt;
}
void dfs1(int u)
{
	int maxson=0;
	dep[u]=dep[fa[u]]+1;
	for(int i=ls[u]; i; i=e[i].next)
	{
		int v=e[i].to; if(v==fa[u]) continue;
		fa[v]=u; dfs1(v); siz[u]+=siz[v];
		if(siz[v]>maxson) son[u]=v,maxson=siz[v];
	}
	siz[u]++;
}
void dfs2(int u,int topf)
{
	dfn[u]=++tot; id[tot]=u;
	top[u]=topf;
	if(!son[u]) return;
	dfs2(son[u],topf);
	for(int i=ls[u]; i; i=e[i].next)
	{
		int v=e[i].to;
		if(v==fa[u]||v==son[u]) continue;
		dfs2(v,v);
	}
}
int lca(int x,int y)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y]) swap(x,y); return y;
}
int main()
{
	scanf("%d%d%d",&n,&m,&root);
	for(int i=1,x,y; i<n; i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
//	fa[root]=root;
	dfs1(root); dfs2(root,root);
	while(m--)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d\n",lca(x,y));
	}
}

KMP

https://www.luogu.com.cn/problem/P3375

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+77;
char s1[N],s2[N];
int nxt[N];
int main()
{
	scanf("%s%s",s1,s2);
	int l1=strlen(s1),l2=strlen(s2);
	for(int i=1,j=0; i<l2; i++)
	{
		while(s2[i]!=s2[j]&&j) j=nxt[j];
		if(s2[i]==s2[j]) j++;
		nxt[i+1]=j;
	}
	for(int i=0,j=0; i<l1; i++)
	{
		while(s1[i]!=s2[j]&&j) j=nxt[j];
		if(s1[i]==s2[j]) j++;
		if(j>=l2) printf("%d\n",i-j+2);
	}
	for(int i=1; i<=l2; i++) printf("%d ",nxt[i]);
}

差分约束

https://www.luogu.com.cn/problem/P5960

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+77;
int n,m,d[N],b[N],p[N],ls[N],cnt;
struct E
{
	int to,next,v;
}e[N<<1];
void add(int u,int v,int val)
{
	e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt; e[cnt].v=val;
}
bool spfa()
{
	memset(d,0x3f,sizeof(d));
	queue<int> q; q.push(n+1);
	d[n+1]=0; b[n+1]=1; p[n+1]++;
	while(!q.empty())
	{
		int u=q.front(); q.pop();
		for(int i=ls[u]; i; i=e[i].next)
		{
			int v=e[i].to;
			if(d[u]+e[i].v<d[v])
			{
				d[v]=d[u]+e[i].v;
				if(!b[v])
				{
					q.push(v),b[v]=1,p[v]++;
					if(p[v]>=n) return 0;
				}
			}
		}
		b[u]=0;
	}
	return 1;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,x,y,z; i<=m; i++) scanf("%d%d%d",&x,&y,&z),add(y,x,z);
	for(int i=1; i<=n; i++) add(n+1,i,0);
	if(!spfa()) printf("NO");
	else for(int i=1; i<=n; i++) printf("%d ",d[i]);
}

矩阵快速幂

https://www.luogu.com.cn/problem/P3390

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=107,mod=1e9+7;
struct M
{
	ll a[N][N]; int n;
	void _1()
	{
		for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j]=0;
		for(int i=1; i<=n; i++) a[i][i]=1;
	}
	void clear()
	{
		for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j]=0;
	}
}A;
int n;ll k;
M mul(M x,M y)
{
	M t; t.n=n; t.clear(); 
	for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) for(int k=1; k<=n; k++) 
		(t.a[i][j]+=(x.a[i][k]*y.a[k][j])%mod)%=mod;
	return t;
}
M power(M x,ll t)
{
	M b; b.n=x.n;
	b._1();
	while(t)
	{
		if(t&1) b=mul(b,x);
		x=mul(x,x); t>>=1;
	}
	return b;
}
int main()
{
	scanf("%d%lld",&n,&k);
	for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) scanf("%lld",&A.a[i][j]);
	A.n=n;
	A=power(A,k);
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=n; j++) printf("%lld ",A.a[i][j]);
		printf("\n");
	}
}

tarjan(强连通)

https://www.luogu.com.cn/problem/P3387

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+77;
int X[N],Y[N],n,m,cnt,Cnt,ls[N],Ls[N],low[N],dfn[N],tot,s[N],top,id,c[N],sum[N],f[N],a[N],ans,d[N],b[N]; 
struct edge
{
	int to,next;
}E[N];
void Add(int u,int v)
{
	E[++Cnt].to=v; E[Cnt].next=Ls[u]; Ls[u]=Cnt; X[Cnt]=u,Y[Cnt]=v;
}
void tarjan(int u)
{
	dfn[u]=low[u]=++tot; b[u]=1;
	s[++top]=u; 
	for(int i=Ls[u]; i; i=E[i].next)
	{
		int v=E[i].to;
		if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
		else if(b[v]) low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u])
	{
		id++;
		while(s[top+1]!=u)
		{
			c[s[top]]=id; sum[id]+=a[s[top]]; b[s[top]]=0; top--;
		}
	}
}
edge e[N];
void add(int u,int v)
{
	if(u==v) return;
	e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt;
	d[v]++;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	for(int i=1,x,y; i<=m; i++) scanf("%d%d",&x,&y),Add(x,y);
	for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i);
	for(int i=1; i<=m; i++) add(c[X[i]],c[Y[i]]);
	queue<int> q;
	for(int i=1; i<=id; i++)
	{
		if(d[i]==0) q.push(i);
		f[i]=sum[i]; ans=max(f[i],ans);
	}
	while(!q.empty())
	{
		int u=q.front(); q.pop();
		for(int i=ls[u]; i; i=e[i].next)
		{
			int v=e[i].to;
			f[v]=max(f[v],f[u]+sum[v]); d[v]--;
			if(!d[v]) q.push(v);
			ans=max(f[v],ans);
		}
	}
	printf("%d",ans);
}


点双

https://www.luogu.com.cn/problem/P3388

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+77;
int dfn[N],low[N],ls[N],f[N],cnt=0,ccnt=0,n,m;
bool cut[N];
struct E
{
	int to,next;
}e[N];
void add(int u,int v)
{
	e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt;
}
void tarjan(int u)
{
	dfn[u]=1;
	dfn[u]=low[u]=++cnt;
	int rd=0;
	for(int i=ls[u]; i; i=e[i].next)
	{
		int v=e[i].to;
		if(!dfn[v])
		{
			f[v]=f[u];
			tarjan(e[i].to);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]&&u!=f[u]) cut[u]=1;
			if(u==f[u]) rd++;
		}
		else low[u]=min(low[u],dfn[v]);
	}
	if(rd>1&&u==f[u]) cut[u]=1;
	
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1; i<=m; i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y); add(y,x);
	}
	for(int i=1; i<=n; i++) f[i]=i;
	for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i);
	for(int i=1; i<=n; i++) ccnt+=cut[i];
	printf("%d\n",ccnt);
	for(int i=1; i<=n; i++) if(cut[i])printf("%d ",i);
}

线性基

https://www.luogu.com.cn/problem/P3812

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=60;
ll _2[N],a[N];
bool bz=0;
int n;
void ins(ll x)
{
	int i=0;
	while(_2[i]<=x) i++;
	for(int j=i; j>=0; j--) if((x&_2[j])!=0)
	{
		if(!a[j])
		{
			a[j]=x; break;
		}
		else x^=a[j];
	}
	if(x==0) bz=1;
}
ll qmax()
{
	ll x=0;
	for(int i=51; i>=0; i--) if((x&_2[i])==0) 
		x=max(x,x^a[i]);
	return x;
}
int main()
{
	scanf("%d",&n);
	_2[0]=1;
	for(int i=1; i<=52; i++) _2[i]=_2[i-1]*2;
	for(ll i=1,x; i<=n; i++) scanf("%lld",&x),ins(x);
	printf("%lld",qmax());
}

exgcd

https://www.luogu.com.cn/problem/P5656

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int gcd(ll a,ll b)
{
	return b==0?a:gcd(b,a%b);
}
void exgcd(ll &x,ll &y,ll a,ll b)
{
	if(b==0)
	{
		x=1,y=0; return ;
	}
	exgcd(x,y,b,a%b);
	int t=x; x=y; y=t-a/b*x;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		ll a,b,c,d;
		scanf("%lld%lld%lld",&a,&b,&c); d=gcd(a,b);
		if(c%d!=0)
		{
			printf("-1\n"); continue;
		}
		ll x=0,y=0,k=0,p=b/d,q=a/d;
		exgcd(x,y,a,b); x*=c/d,y*=c/d;
		if(x<=0) k=ceil((1.0-x)/p),x+=p*k,y-=q*k;
		else if(x>0) k=(x-1)/p,x-=p*k,y+=q*k;
		if(y>0) printf("%lld %lld %lld %lld %lld\n",(y-1)/q+1,x,(y-1)%q+1,x+(y-1)/q*p,y);
		else printf("%lld %lld\n",x,y+q*(ll)ceil((1.0-y)/q));
	}
}

边双

void tarjan(int u,int fa){
	dfn[u] = low[u] = ++tim;
	for(int i = head[u];i != -1;i = e[i].next){
		int v = e[i].to;
		if(v == fa) continue;
		if(!dfn[v]){
			tarjan(v,u);
			low[u] = min(low[u],low[v]);
			if(low[v] > dfn[u])//边双充要条件
				vis[i] = vis[i ^ 1] = 1;
		}else
			low[u] = min(low[u],dfn[v]);
	}
}

树上差分(前缀和)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+7,inf=1e18;
vector<int> e[N],dep,ans;
int fa[N][23];
void dfs1(int u)
{
	for(int v:e[u])
	{
		if(v==fa[u][0]) continue;
		dep[v]=dep[u]+1;
		fa[v][0]=u;
		dfs1(v);
	}
}
void dfs2(int u)
{
	for(int v:e[u])
	{
		if(v==fa[u][0]) continue;
		ans[v]+=ans[u];
		dfs2(v);
	}
}
void lca(int u,int v)
{
	int x=u,y=v;
	if(dep[u]<dep[v]) swap(u,v),swap(x,y);
	if(dep[u]!=dep[v])
	{
		for(int i=20; i>=0; i--)
		{
			if(dep[fa[u][i]]>dep[v])
				u=fa[u][i];
		}
		if(fa[u][0]==v)
		{
			ans[u]++;
			for(auto t:e[x])
				if(t!=fa[x][0])
					ans[t]--;
			return;
		}
		u=fa[u][0];
	}
	for(int i=20; i>=0; i--)
	{
		if(fa[u][i]!=fa[v][i])
		{
			u=fa[u][i];
			v=fa[v][i];
		}
	}
	ans[u]++;
	ans[v]++;
	for(auto t:e[x])
		if(t!=fa[x][0])
			ans[t]--;
	for(auto t:e[y])
		if(t!=fa[y][0])
			ans[t]--;
}
void O_o()
{
	int n,m;
	cin>>n>>m;
	dep.resize(n+1);
	ans.resize(n+1);
	vector<array<int,2>> p;
	for(int i=1; i<n; i++)
	{
		int x,y;
		cin>>x>>y;
		e[x].push_back(y);
		e[y].push_back(x);
		p.push_back({x,y});
	}
	dep[1]=1;
	dfs1(1);
	for(int i=1; i<=20; i++)
	{
		for(int u=1; u<=n; u++)
		{
			fa[u][i]=fa[fa[u][i-1]][i-1];
		}
	}
	
	for(int i=1; i<=m; i++)
	{
		int x,y;
		cin>>x>>y;
		if(x==y) continue;
		lca(x,y);
	}
	
	dfs2(1);
	for(int i=n-1; i>=1; i--) 
	{
		auto[x,y]=p[i-1];
		if(dep[x]<dep[y]) swap(x,y);
		if(ans[x]==m)
		{
			cout<<i<<"\n";
			return;
		}
	}
	cout<<"-1\n";
}
signed main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cout<<fixed<<setprecision(2);
	int T=1;
//	cin>>T;
	while(T--)
	{
		O_o();
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值