noip day0
马上就要打酱油了>_<,真是害怕。昨天就整理了一下noip要写的模板
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define ll long long using namespace std; const int maxn=100000+233; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } struct saber{ int an,l,r; }t[maxn<<2]; int tt[maxn],a[maxn],b[maxn],dp[maxn],ans,n; inline void build(int k,int l,int r){ t[k].l=l;t[k].r=r; if(l==r)return ; int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } inline int ask(int k,int x,int y){ int l=t[k].l,r=t[k].r; if(l==x&&r==y)return t[k].an; int mid=l+r>>1; if(mid>=y)return ask(k<<1,x,y); else if(x>mid)return ask(k<<1|1,x,y); else return max(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y)); } inline void add(int k,int wi,int fin){ int l=t[k].l,r=t[k].r; if(l==fin&&r==fin){t[k].an=wi;return;} int mid=l+r>>1; if(mid>=fin)add(k<<1,wi,fin); else add(k<<1|1,wi,fin); t[k].an=max(t[k<<1].an,t[k<<1|1].an); } int main(){ n=read(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=n;i++)b[i]=read(); for(int i=1;i<=n;i++)tt[b[i]]=i; for(int i=1;i<=n;i++)a[i]=tt[a[i]]; build(1,1,n); for(int i=1;i<=n;i++){ int x=ask(1,1,a[i]); dp[i]=x+1; add(1,dp[i],a[i]); ans=max(ans,dp[i]); } cout<<ans; }
【模板】最长公共子序列
类似导弹拦截
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> #define _x .first #define _y .second using namespace std; const int maxn=10000+2333; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<3)+(an<<1)+(ch^48);ch=getchar();} return an; } int tmp; struct saber{ int l,r,t,id; }q[maxn]; vector< pair<int,int > > change; int n,m,a[maxn],block,link[maxn],cntq,cnt,ans[maxn]; int color[maxn*10],size; char c; bool operator <(saber x,saber y){return (link[x.l]<link[y.l])||(link[x.l]==link[y.l]&&x.r<y.r)||(link[x.l]==link[y.l]&&x.r==y.r&&x.t<y.t);} inline void Change(int x,int i){ if(change[x] _x>=q[i].l&&change[x] _x<=q[i].r){ color[a[change[x] _x]]--; if(color[a[change[x] _x]]==0)tmp--; if(color[change[x] _y]==0)tmp++; color[change[x] _y]++; } swap(a[change[x] _x],change[x] _y); } int main(){ // ios::sync_with_stdio(0); cin>>n>>m; size=sqrt(n); for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=m;i++){ link[i]=block+1; if(!(i%size))block++; } change.push_back(make_pair(0,0)); for(int i=1;i<=m;i++){ cin>>c; if(c==‘R‘){ ++cntq; int x,y;cin>>x>>y; change.push_back( make_pair(x,y) ); } else{ int x,y;cin>>x>>y; q[++cnt]=(saber){x,y,cntq,cnt}; } } sort(q+1,q+1+cnt); int L=0,R=0,now=0; for(int i=1;i<=cnt;i++){ while(L<q[i].l){color[a[L]]--;if(!color[a[L]])tmp--;L++;} while(L>q[i].l){L--;color[a[L]]++;if(color[a[L]]==1)tmp++;} while(R<q[i].r){R++;color[a[R]]++;if(color[a[R]]==1)tmp++;} while(R>q[i].r){color[a[R]]--;if(color[a[R]]==0)tmp--;R--;} while(now<q[i].t){now++,Change(now,i);} while(now>q[i].t){Change(now,i);now--;} ans[q[i].id]=tmp; } for(int i=1;i<=cnt;i++)cout<<ans[i]<<"\n"; return 0; }
【模板】分块/带修改莫队(数颜色)
分块处理<优雅的暴力>
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define ll long long const int mod=1e9+7; using namespace std; int n,T; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } struct saber{ ll a[5][5]; }b,a; saber operator *(saber A,saber B){ saber re; memset(re.a,0,sizeof re.a); for(int k=1;k<=3;k++) for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) re.a[i][j]=(re.a[i][j]+A.a[i][k]*B.a[k][j])%mod; return re; } inline saber work(saber x,int y){ saber re; re=x; while(y){ if(y&1)re=re*x; x=x*x; y>>=1; } return re; } int main(){ b.a[1][3]=1;b.a[2][1]=1; b.a[3][3]=1;b.a[3][2]=1; a.a[1][1]=1;a.a[1][2]=1;a.a[1][3]=1; T=read(); while(T){ T--; n=read(); if(n<=3){cout<<"1\n";continue;} saber k=work(b,n-4); k=a*k; cout<<k.a[1][3]<<"\n"; } }
P1939 【模板】矩阵加速(数列)
推出矩阵乱搞就好了
#include<iostream> #include<algorithm> #include<cstdlib> #include<algorithm> using namespace std; int read(){ int an=0,f=1; char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘)f=-f;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } const int maxn=5099; const int maxm=200999; int fa[maxn],cnt,so[maxm]; long long ans; int m,n,tot; struct saber{ int from,to,wi; }b[maxm]; void add(int x,int y,int z){ cnt++; b[cnt].from=x; b[cnt].to=y; b[cnt].wi=z; } bool pai(int x,int y){ return b[x].wi<b[y].wi; } int found(int x){ if(fa[x]!=x)fa[x]=found(fa[x]); return fa[x]; } int main(){ n=read();m=read(); for(int i=1;i<=m;i++){ int x,y,z; x=read();y=read();z=read(); add(x,y,z); } for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m;i++)so[i]=i; sort(so+1,so+m+1,pai); for(int i=1;i<=m;i++){ int x=b[so[i]].from; int y=b[so[i]].to; int f1=found(x);int f2=found(y); if(f1!=f2){ans+=b[so[i]].wi;fa[f1]=f2;} } cout<<ans; return 0; }
【模板】最小生成树
记得路径压缩
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; #define IN 599962 int a[IN],c[IN]; int m,n; int LO(int i){return (-i)&i;} int ans(int k){ int ans=0; for(int i=k;i>0;i-=LO(i))ans+=c[i]; return ans; } void F(int k){ printf("%d",ans(k)); } void F(int k1,int k2,int k3){ for(int i=k1;i<=n;i+=LO(i))c[i]+=k3; for(int i=k2+1;i<=n;i+=LO(i))c[i]-=k3; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); for(int j=i;j<=n;j+=LO(j))c[j]+=a[i]; int j;j=i+1; for(j;j<=n;j+=LO(j))c[j]-=a[i]; } for(int j=1;j<=m;j++){ int s; scanf("%d",&s); if(s==1){int k1,k2,k3; scanf("%d%d%d",&k1,&k2,&k3); F(k1,k2,k3); } else{int k; scanf("%d",&k); F(k); printf("\n"); } } return 0; }
P3368 【模板】树状数组 2
查分树状数组
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> #include<cstring> #define ll long long using namespace std; const int maxn=10000+2333; const ll mod=23333333333ll; const int sand=107; char ch[maxn]; ll a[maxn]; ll hax(){ int len=strlen(ch); ll re=0; for(int i=0;i<len;i++)re=(re*sand+ch[i])%mod; return re; } int n; int main(){ ios::sync_with_stdio(0); cin>>n; for(int i=1;i<=n;i++){ cin>>ch; a[i]=hax(); } sort(a+1,a+1+n); int tot=unique(a+1,a+1+n)-a-1; cout<<tot; return 0; }
【模板】字符串哈希
哈希判断是否重复,wa了该取模数。O2之后某个溢出哈希就会挂~\(≧▽≦)/~啦啦啦
最短路
#include<iostream> #include<cstdio> #include<cstdlib> #include<queue> #include<algorithm> #include<cstring> #define _X .first #define _Y .second #define ll long long using namespace std; const int maxn=10000+2333; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } int n,m,S,cnt; int f[maxn]; ll dis[maxn]; pair<ll,int>now; priority_queue<pair<ll,int> >q; struct saber{ int nex,to,wi; }b[(500000<<1)+233]; inline void add(int x,int y,int z){ cnt++; b[cnt].wi=z; b[cnt].to=y; b[cnt].nex=f[x]; f[x]=cnt; } void dij(){ for(int i=1;i<=n;i++)dis[i]=2147483647; dis[S]=0; q.push(make_pair(0,-S)); while(!q.empty()){ now=q.top();q.pop(); int x=-now _Y; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(dis[v]>dis[x]+b[i].wi){ dis[v]=dis[x]+b[i].wi; q.push(make_pair(-dis[v],-v)); } } } } int main(){ n=read();m=read();S=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read(); add(x,y,z); } dij(); for(int i=1;i<=n;i++) cout<<dis[i]<<" "; return 0; }
dijkstra
传说他稳定
#include<iostream> #include<cstdio> #include<cstdlib> #include<queue> #include<algorithm> #define ll long long using namespace std; const ll INT=2147483647LL; ll read(){ ll an=0,f=1; char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } ll x,y,z; ll f[10000+99],spf[10000+99],m,n,k,wi[500099],sum; bool cx[10000+99]; queue<ll>q; struct saber{ int nex,to; }b[500099]; void add(ll x,ll y,ll z){ sum++; b[sum].nex=f[x]; b[sum].to=y; f[x]=sum; wi[sum]=z; } void spfa(){ while(!q.empty()){ ll v=q.front(); q.pop();cx[v]=0; for(int i=f[v];i;i=b[i].nex){ if(spf[b[i].to]>spf[v]+wi[i]){ spf[b[i].to]=spf[v]+wi[i]; if(!cx[b[i].to]){ q.push(b[i].to); cx[b[i].to]=1;} } } } } int main(){ n=read();m=read();k=read(); for(int i=0;i<=n;i++)spf[i]=INT; for(int i=1;i<=m;i++){ x=read();y=read(),z=read(); add(x,y,z);} q.push(k);spf[k]=0; cx[k]=1; spfa(); for(int i=1;i<=n;i++)cout<<spf[i]<<" "; return 0; }
SPFA
不知道双向队列那个快?[>_<]
线段树模板
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #define ll long long using namespace std; const ll maxn=100000+233; inline ll read(){ ll an=0,f=1; char ch=getchar(); while(ch<‘0‘||‘9‘<ch){ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<1)+(an<<3)+(ch^48);ch=getchar();} return an; } struct saber{ ll l,r,lazy,sum; }t[maxn<<4]; ll n,m; inline void build(ll k,ll l,ll r){ t[k].l=l;t[k].r=r; if(l==r){t[k].sum=read();return;} ll mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); t[k].sum=t[k<<1].sum+t[k<<1|1].sum; } inline void change(ll k){ ll x=t[k].r+1-t[k].l; t[k<<1].lazy+=t[k].lazy; t[k<<1|1].lazy+=t[k].lazy; t[k<<1].sum+=t[k].lazy*(x+1>>1); t[k<<1|1].sum+=t[k].lazy*(x>>1); t[k].lazy=0; } inline ll ask(ll k,ll x,ll y){ ll l=t[k].l,r=t[k].r; if(t[k].lazy)change(k); if(y==r&&l==x){return t[k].sum;} ll mid=l+r>>1; if(y<=mid)return ask(k<<1,x,y); else if(mid<x)return ask(k<<1|1,x,y); else return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y); } inline void add(ll k,ll x,ll y,ll wi){ if(t[k].lazy)change(k); ll l=t[k].l,r=t[k].r; if(y==r&&l==x){t[k].sum+=(r-l+1)*wi;t[k].lazy+=wi;return;} ll mid=l+r>>1; if(y<=mid)add(k<<1,x,y,wi); else if(mid<x)add(k<<1|1,x,y,wi); else {add(k<<1,x,mid,wi);add(k<<1|1,mid+1,y,wi);} t[k].sum=t[k<<1].sum+t[k<<1|1].sum; } int main(){ n=read();m=read(); build(1,1,n); for(;m;m--){ ll pd=read(),x=read(),y=read(); if(pd==1){ ll v=read(); add(1,x,y,v); } else { cout<<ask(1,x,y)<<"\n"; } } }
线段树
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #define ll long long using namespace std; inline ll read(){ ll an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<3)+(an<<1)+(ch^48);ch=getchar();} return an; } const ll maxn=100000+233; ll link[maxn],a[maxn],b[3000],size,add[3000],block,n,m,l[3000],r[3000]; int main(){ ios::sync_with_stdio(0); n=read();m=read(); size=sqrt(n); l[1]=1; for(ll i=1;i<=n;i++)a[i]=read(); for(ll i=1;i<=n;i++){ link[i]=block+1; b[block+1]+=a[i]; if(!(i%size)){ block++; l[block+1]=i+1; r[block]=i; } } if(n%size)r[++block]=n; for(;m;m--){ ll pd=read(); if(pd==1){ ll L=read(),R=read(),p=read(); ll chl=link[L],chr=link[R]; if(chl^chr){ for(ll i=L;i<=r[chl];i++)a[i]+=p,b[chl]+=p; for(ll i=l[chr];i<=R;i++)a[i]+=p,b[chr]+=p; for(ll i=chl+1;i<chr;i++)add[i]+=p; } else{ for(ll i=L;i<=R;i++)a[i]+=p; } } else { ll ans=0,L=read(),R=read(); ll chl=link[L],chr=link[R]; if(chl^chr){ for(ll i=L;i<=r[chl];i++)ans+=add[chl]+a[i]; for(ll i=l[chr];i<=R;i++)ans+=add[chr]+a[i]; for(ll i=chl+1;i<chr;i++)ans+=add[i]*(r[i]-l[i]+1)+b[i]; } else{ for(ll i=L;i<=R;i++)ans+=a[i]+add[i]; } cout<<ans<<"\n"; } } }
分块
分块还是好写
【模板】树状数组 1
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; #define IN 5999620 int a[IN],c[IN]; int LO(int x){return (-x)&x;} int m,n; int q,w,e; void FF(int x,int y){ for(int k=x;k<=n;k+=LO(k)) c[k]+=y; } int S(int s){int ans=0; for(int j=s;j>0;j-=LO(j)) ans+=c[j]; return ans; } void FFF(int i,int j){ cout<<S(j)-S(i)<<endl; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){scanf("%d",&a[i]); for(int j=i;j<=n;j+=LO(j)) c[j]+=a[i];} for(int i=1;i<=m;i++){ scanf("%d%d%d",&q,&w,&e); if(q==1)FF(w,e); else FFF(w-1,e); } return 0; }
树状数组
就是2去掉差分
【模板】堆
手打堆
#include<iostream> #include<cstdio> #include<cstdlib> inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<3)+(an<<1)+ch-48;ch=getchar();} return an*f; } const int maxn=100000+23; using namespace std; int q; int t[maxn],tot; inline void add(int x){ tot++; t[tot]=x; for(int i=tot,j=i>>1;j;i=j,j=i>>1){ if(t[j]>t[i])swap(t[i],t[j]); } } inline void pop(){ t[1]=t[tot];tot--; for(int i=1,j=i<<1;j<=tot;i=j,j=i<<1){ if(j+1<=tot&&t[j+1]<t[j]) ++j; if(t[i]<t[j])break; else swap(t[i],t[j]); } } inline int getans(){ return t[1]; } int main(){ q=read(); ios::sync_with_stdio(0); while(q){ q--; int x=read(); if(x==1)add( read() ); else if(x==2)cout<<getans()<<"\n"; else pop(); } }
堆
【模板】最近公共祖先(LCA)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int read(){ int an=0,f=1; char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘)f=-f;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return f*an; } const int maxn=500000+999; int n,m,s,cnt; int f[maxn],fa[maxn][25],deep[maxn]; bool vis[maxn]; int x,y; struct saber{ int nex,to; }b[maxn*2]; void add(int x,int y){ cnt++; b[cnt].nex=f[x]; b[cnt].to=y; f[x]=cnt;} void dfs(int x){ vis[x]=1; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!vis[v]){ fa[v][0]=x;deep[v]=deep[x]+1; for(int j=1;j<=20;j++){ if(!fa[fa[v][j-1]][j-1])break; fa[v][j]=fa[fa[v][j-1]][j-1];} dfs(v); } } } int lca(int u,int v){ if(deep[u]>deep[v])swap(u,v); for(int i=20;i>=0;i--) if(deep[fa[v][i]]>=deep[u])v=fa[v][i]; if(u==v)return u; for(int i=20;i>=0;i--) if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i]; if(u==v)return u; return fa[u][0]; } void Lca(int x,int y){ int ans=lca(x,y); printf("%d\n",ans); } int main(){ n=read();m=read();s=read(); for(int i=1;i<n;i++){ x=read();y=read(); add(x,y);add(y,x);} deep[s]=1; dfs(s); for(int i=1;i<=m;i++){ x=read();y=read(); Lca(x,y);} return 0; }
倍增
#include<iostream> #include<cstdio> #include<cstdlib> #include<queue> #include<algorithm> using namespace std; int read(){ int an=0,f=1;char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘)f=-f;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } int n,m,s,cnt,qf[500099],f[500099],fa[500099],ans[500099<<1]; int x,y; bool vis[500099]; int found(int x){ if(fa[x]!=x)fa[x]=found(fa[x]); return fa[x];} struct saber{ int to,nex; }b[500099<<1]; struct question{ int to,nex; }qu[500099<<1]; void add(int x,int y){ cnt++;b[cnt].to=y; b[cnt].nex=f[x];f[x]=cnt; } void add(int x,int y,int z){ qu[z].to=y; qu[z].nex=qf[x]; qf[x]=z; } void dfs(int x){ fa[x]=x;vis[x]=1; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!vis[v]){ dfs(v); fa[v]=x; } } for(int i=qf[x];i;i=qu[i].nex){ int v=qu[i].to; if(vis[v]){ ans[i]=found(v); if(i&1)ans[i+1]=ans[i]; else ans[i-1]=ans[i]; } } } int main(){ n=read();m=read();s=read(); for(int i=1;i<n;i++){ int x,y;x=read();y=read(); add(x,y);add(y,x); } for(int i=1;i<=m;i++){ x=read();y=read(); add(x,y,(i<<1)-1);add(y,x,(i<<1)); } dfs(s); for(int i=1;i<=m;i++){ printf("%d\n",ans[i<<1]);} return 0; }
tarjian
【模板】网络最大流
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<queue> #include<cstring> const int maxn=100000+2333; const int maxm=100000+99999; const int INT=1e7; using namespace std; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||‘9‘<ch){ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<1)+(an<<3)+(ch^48);ch=getchar();} return an; } int f[maxn],S,T,n,m,cnt=1; struct saber{ int wi,nex,to; }b[maxn<<2]; inline void add(int x,int y,int z){ cnt++; b[cnt].to=y; b[cnt].wi=z; b[cnt].nex=f[x]; f[x]=cnt; } queue<int>q; int dis[maxn]; bool vis[maxn]; inline int bfs(){ while(!q.empty())q.pop(); q.push(S); memset(dis,-1,sizeof dis); dis[S]=0; while(!q.empty()){ int x=q.front();q.pop(); for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(dis[v]<0&&b[i].wi){ dis[v]=dis[x]+1; if(v==T)return 1; q.push(v); } } } return 0; } inline int dfs(int x,int li){ if(x==T||!li)return li; int used=li; vis[x]=1; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!vis[v]){ if(dis[v]==dis[x]+1&&used&&b[i].wi){ int re=dfs(v,min(b[i].wi,used)); used-=re; b[i].wi-=re; b[i^1].wi+=re; } } } return li-used; } void dinic(){ int ans=0; while(bfs()){ memset(vis,0,sizeof vis); ans+=dfs(S,INT); } cout<<ans; } int main(){ n=read();m=read();S=read();T=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read(); add(x,y,z); add(y,x,0); } dinic(); return 0; }
网络流
真noip
【模板】最小费用最大流
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<queue> #include<cstring> const int maxn=100000+2333; const int maxm=100000+99999; const int INT=1e7; using namespace std; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||‘9‘<ch){ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<1)+(an<<3)+(ch^48);ch=getchar();} return an; } int f[maxn],S,T,n,m,cnt=1; struct saber{ int wi,nex,to,fi; }b[maxn<<2]; inline void add(int x,int y,int z,int fi){ cnt++; b[cnt].to=y; b[cnt].wi=z; b[cnt].fi=fi; b[cnt].nex=f[x]; f[x]=cnt; } deque<int>q; int dis[maxn]; bool vis[maxn],in[maxn]; inline int bfs(){ while(!q.empty())q.pop_front(); q.push_back(S); for(int i=0;i<=n+2;i++)dis[i]=INT; memset(in,0,sizeof in); dis[S]=0; while(!q.empty()){ int x=q.front();q.pop_front();in[x]=0; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(dis[v]>dis[x]+b[i].fi&&b[i].wi){ dis[v]=dis[x]+b[i].fi; if(!in[v]){ in[v]=1; if(!q.empty()&&dis[v]<dis[q.front()])q.push_front(v); else q.push_back(v); } } } } return dis[T]<INT; } inline int dfs(int x,int li){ if(x==T||!li)return li; int used=li; vis[x]=1; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!vis[v]){ if(dis[v]==dis[x]+b[i].fi&&used&&b[i].wi){ int re=dfs(v,min(b[i].wi,used)); used-=re; b[i].wi-=re; b[i^1].wi+=re; } } } return li-used; } void dinic(){ int ans=0; int fe=0; while(bfs()){ memset(vis,0,sizeof vis); int v=dfs(S,INT); ans+=v; fe+=dis[T]*v; } cout<<ans<<" "<<fe; } int main(){ n=read();m=read();S=read();T=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read(),fi=read(); add(x,y,z,fi); add(y,x,0,-fi); } dinic(); return 0; }
费用流
在网络流上加最短路
【模板】负环
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define ll long long using namespace std; const int maxn=200000+2333; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } struct saber{ int nex,wi,to; }b[maxn<<1]; int f[maxn],dis[maxn],T,cnt,n,m,flag; bool vis[maxn]; inline void add2(int x,int y,int z){ cnt++; b[cnt].to=y; b[cnt].wi=z; b[cnt].nex=f[x]; f[x]=cnt; } inline void add(int x,int y,int z){ if(z>0)add2(x,y,z),add2(y,x,z); else add2(x,y,z); } inline void dfs(int x){ if(vis[x]){flag=1;return ;} vis[x]=1; for(int i=f[x];i&&!flag;i=b[i].nex){ int v=b[i].to; if(dis[v]>dis[x]+b[i].wi){ dis[v]=dis[x]+b[i].wi; dfs(v); } } vis[x]=0; } int main(){ T=read(); ios::sync_with_stdio(0); while(T){T--; flag=0; cnt=0; memset(vis,0,sizeof vis); memset(dis,0,sizeof dis); memset(f,0,sizeof f); n=read();m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(),z=read(); add(x,y,z); } for(int i=1;i<=n&&!flag;i++){ dfs(i); } if(!flag)cout<<"N0\n"; else cout<<"YE5\n"; } }
负环
dfs判负环
【模板】二分图匹配
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<queue> #define ll long long using namespace std; const int maxn=3000; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<3)+(an<<1)+ch-‘0‘;ch=getchar();} return an*f; } int f[maxn<<1],ans,cnt,n,m,e; struct saber{ int nex,to; }b[5000000]; inline void add(int x,int y){ cnt++; b[cnt].to=y; b[cnt].nex=f[x]; f[x]=cnt; } int in[maxn<<1]; bool vis[maxn<<1]; inline int dfs(int x){ for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!in[v]){in[v]=x;return 1;} } for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(vis[v])continue; vis[v]=1; if(dfs(in[v])){in[v]=x;return 1;} } return 0; } int main(){ n=read();m=read();e=read(); for(int i=1;i<=e;i++){ int x=read(),y=read(); if(y>m); else add(x,n+10+y); } for(int i=1;i<=n;i++){ memset(vis,0,sizeof vis); if(dfs(i))ans++; } cout<<ans; }
匈牙利算法
莫名其妙<网络流跑不A(竟然不是T
【模板】缩点
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<queue> #include<stack> #define ll long long using namespace std; const int maxn=1e4+233+17+9; const int maxm=1e5+2333+17+9+4950; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<3)+(an<<1)+ch-‘0‘;ch=getchar();} return an*f; } int scc,f[maxn],ff[maxn],id; int dag[maxn],dfn[maxn],low[maxn],wi[maxn]; int bel[maxn]; int dp[maxn],cnt,ans,n,m,ins[maxn]; bool vis[maxn],in[maxn]; struct saber{ int nex,to; }b[maxm],bb[maxm]; stack<int>s; inline void add(int x,int y){ cnt++; b[cnt].to=y; b[cnt].nex=f[x]; f[x]=cnt; } inline void add2(int x,int y){ cnt++; ins[y]++; bb[cnt].to=y; bb[cnt].nex=ff[x]; ff[x]=cnt; } inline void dfs(int x){ id++; dfn[x]=low[x]=id; in[x]=vis[x]=1; s.push(x); for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!vis[v]){ dfs(v); low[x]=min(low[x],low[v]); } else if(in[v])low[x]=min(low[x],dfn[v]); } if(dfn[x]==low[x]){ int z=22333;scc++; while(z!=x){ z=s.top(); bel[z]=scc; dag[scc]+=wi[z]; in[z]=0; s.pop(); } } } queue<int>q; inline void rebuild(){ cnt=1; for(int i=1;i<=n;i++){ for(int j=f[i];j;j=b[j].nex){ int v=b[j].to; if(bel[i]!=bel[v])add2(bel[i],bel[v]); } } } inline void top_sort(){ int flag,l=1; while(l<=n){ memset(vis,0,sizeof vis); memset(dp,0,sizeof dp); while(l<=n){ if(!ins[l]){q.push(l);flag=l;break;} else l++; } dp[flag]=dag[flag]; while(!q.empty()){ int x=q.front();q.pop();vis[x]=0; for(int i=ff[x];i;i=bb[i].nex){ int v=bb[i].to; if(dp[v]<dp[x]+dag[v]){ dp[v]=dp[x]+dag[v]; if(!vis[v]){ q.push(v); vis[v]=1; } } } ans=max(ans,dp[x]); } l=l+1; } } int main(){ n=read();m=read(); for(int i=1;i<=n;i++)wi[i]=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(); add(x,y); } for(int i=1;i<=n;i++) if(!vis[i])dfs(i); rebuild(); top_sort(); cout<<ans; return 0; }
dp
不要跑最短路>>
【模板】割点(割顶)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<queue> #include<stack> #define ll long long using namespace std; const int maxn=100000+2333+17+9+4950; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=(an<<3)+(an<<1)+ch-‘0‘;ch=getchar();} return an*f; } int f[maxn],n,m,cnt=1,id; bool cut[maxn],vis[maxn]; int dfn[maxn],low[maxn],ans; struct saber{ int nex,to; }b[maxn<<1]; inline void add(int x,int y){ cnt++; b[cnt].to=y; b[cnt].nex=f[x]; f[x]=cnt; } inline int dfs(int x,int fa){ int sum=0;bool cu=0; id++; dfn[x]=low[x]=id;vis[x]=1; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(v==fa)continue; if(!vis[v]){ sum++; dfs(v,x); low[x]=min(low[x],low[v]); if(low[v]>=dfn[x])cu=1; } else low[x]=min(low[x],dfn[v]); } if(!fa){if(sum>1)ans++,cut[x]=1;} else if(cu)ans++,cut[x]=1; } int main(){ n=read();m=read(); for(int i=1;i<=m;i++){ int x=read(),y=read(); add(x,y);add(y,x); } for(int i=1;i<=n;i++) if(!vis[i])dfs(i,0); cout<<ans<<"\n"; for(int i=1;i<=n;i++)if(cut[i])cout<<i<<" "; return 0; }
割点
贪心,先找根,然后判下面是否割
【模板】卢卡斯定理
#include<iostream> #include<cstdlib> #define ll long long using namespace std; ll T,p; ll f[500000]; ll ks(ll y,ll k){ ll s=y,ans=1; while(k){ if(k&1)ans=ans*s%p; s=s*s%p; k>>=1; } return ans%p; } ll C(ll n,ll m){ if(m>n)return 0; return f[n]*ks(f[m]*f[n-m],p-2)%p; } ll Luc(ll n,ll m){ if(!m)return 1; return (Luc(n/p,m/p)*C(n%p,m%p))%p; } int main(){ cin>>T; while(T){ ll n,m; T--; cin>>n>>m>>p; f[0]=1; for(int i=1;i<=p;i++)f[i]=f[i-1]*i%p; cout<<Luc(n+m,m)<<endl;} return 0; }
组合数
数论
【模板】ST表
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=100000+999; int read(){ int f=1,an=0; char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘)f=-f;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+(ch-‘0‘);ch=getchar();} return an*f; } int x,y,n,m; struct saber{ int l,r,M; }tr[maxn*4+999]; int a[maxn]; void build(int k,int l,int r){ int mid=(l+r)>>1; tr[k].l=l;tr[k].r=r; if(l==r){tr[k].M=a[l];return;} build(k<<1,l,mid); build(k<<1|1,mid+1,r); tr[k].M=max(tr[k<<1].M,tr[k<<1|1].M); } int ask(int k,int i,int j){ int l=tr[k].l,r=tr[k].r; if(l==i&&j==r){ return tr[k].M;} int mid=(l+r)>>1; if(j<=mid){return ask(k<<1,i,j);} else if(i>mid){return ask(k<<1|1,i,j);} else {return max(ask(k<<1,i,mid),ask(k<<1|1,mid+1,j));} } int main(){ n=read();m=read(); for(int i=1;i<=n;i++)a[i]=read(); build(1,1,n); for(int i=1;i<=m;i++){ x=read();y=read(); printf("%d\n",ask(1,x,y)); } return 0; }
线段树
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> using namespace std; const int maxn=1e5+2333; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } int st[maxn][20],n,q; int main(){ ios::sync_with_stdio(0); n=read();q=read(); for(int i=1;i<=n;i++)st[i][0]=read(); for(int j=1;j<=20;j++) for(int i=1;i+(1<<j-1)-1<=n;i++) st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]); while(q){q--; int l=read(),r=read(); int k=log2(r-l+1); cout<<max(st[l][k],st[r-(1<<k)+1][k])<<"\n"; } return 0; }
st
【模板】矩阵快速幂
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> typedef long long ll; using namespace std; ll n,m,i,j,k; struct Matrix{ ll a[105][105]; inline Matrix operator *(const Matrix &b)const { Matrix ret; for (ll i=1;i<=n;i++) for (ll j=1;j<=n;j++) { ret.a[i][j]=0; for (ll k=1;k<=n;k++) ret.a[i][j]+=a[i][k]*b.a[k][j],ret.a[i][j]%=1000000007; } return ret; } }a; inline ll read() { ll iep=1,ret=0;char ch=getchar(); while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) iep=-1;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘){ret=ret*10+ch-‘0‘;ch=getchar();} return ret*iep; } Matrix ksm(Matrix a,ll x) { Matrix ret,k;k=a; ret=a;x--; for (;x;x>>=1,k=k*k) if (x&1) ret=ret*k; return ret; } int main() { n=read();k=read(); for (i=1;i<=n;i++) for (j=1;j<=n;j++) a.a[i][j]=read(); a=ksm(a,k); for (i=1;i<=n;i++) { for (j=1;j<n;j++) printf("%d ",a.a[i][j]); printf("%d\n",a.a[i][n]); } }
QAQ
想当初不会啊
时间: 2024-10-02 19:30:38