noip2017酱油记前篇
分类:
IT文章
•
2025-01-26 14:25:49
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]<<"
";
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
";continue;}
saber k=work(b,n-4);
k=a*k;
cout<<k.a[1][3]<<"
";
}
}
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("
");
}
}
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)<<"
";
}
}
}
线段树
#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<<"
";
}
}
}
分块
分块还是好写
【模板】树状数组 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()<<"
";
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
",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
",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
";
else cout<<"YE5
";
}
}
负环
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<<"
";
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
",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])<<"
";
}
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
",a.a[i][n]);
}
}
QAQ
想当初不会啊