傻子专用


要是有什么没放上去的,就是忘了或者懒得放了


杂项

杂项

缺省源
#include<bits/stdc++.h>

namespace Mudrock_csy {
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define pii pair<int,int>
    #define cerr_time cerr<<clock()*1.0/CLOCKS_PER_SEC<<endl
    #define endl '\n'

    inline int read() {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-48;c=getchar();}
        return x*f;
    }
} using namespace Mudrock_csy;

namespace Mudrock_mod {
    const int mod = 998244353 ;
    inline int add(int x,int y) {return x+y>=mod?x+y-mod:x+y;}
    inline int del(int x,int y) {return x>=y?x-y:x-y+mod;}
    inline int mul(int x,int y) {return 1ll*x*y%mod;}
    inline void Add(int &x,int y) { x=(x+y>=mod?x+y-mod:x+y); }
    inline void Del(int &x,int y) { x=(x>=y?x-y:x-y+mod); }
    inline void Mul(int &x,int y) { x=(1ll*x*y%mod); }
    inline int power(int x,int t) {
        int ans=1; while(t) {
            if(t&1) ans=mul(ans,x); 
            x=mul(x,x); t>>=1;
        } return ans ;
    }
    inline int inv(int x) {return power(x,mod-2);}
} // using namespace Mudrock_mod;

int main()
{
    #ifndef Mudrock
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    #endif
}
离散化

int ls[MAX];
void lsh(int x[],int n) {
    for(int i=1;i<=n;i++)
        ls[i]=x[i];
    sort(ls+1,ls+n+1);
    int m=unique(ls+1,ls+n+1)-ls-1;
    for(int i=1;i<=n;i++)
        x[i]=lower_bound(ls+1,ls+m+1,x[i])-ls;
}



注意事项:
    之前我函数里复制直接用的memcpy,会报错
    对于函数中以数组为参数时,是传址而不是传整个数组空间
    所以sizeof对应的长度并非x的长度

运行时间

cerr<<clock()*1.0/CLOCKS_PER_SEC<<endl;

随机数

上面那个在Windows下用,下面那个在Linux下用


mt19937 myrand(*(new unsigned));
mt19937 myrand(clock());

inline int rand(int l,int r) { return uniform_int_distribution<int>(l,r)(myrand); }

cout<<rand(-10,10)<<endl;
// 用于生成 l~r 之间的随机数

拿purfer序列建树

int pru[MAX],d[MAX];
int main()
{
    int n=10,top=1,mem=0; cout << n << endl ;
    for(int i=1;i<=n-1;i++) d[pru[i]=rand(1,n)]++;
    for(int i=1;i<=n-1;i++) {
        if(!mem) {while(d[top])top++;mem=top;}
        cout << pru[i] << " " << mem << endl ;
        if(!(--d[pru[i]])&&pru[i]<top) mem=pru[i];
        else mem=0,top++;
    }
}
对拍

Windows下的,Sleep单位为毫秒,/w 是用来处理多余空格空行的

#include<bits/stdc++.h>
using namespace std;
int main(){
    
    system("g++ data.cpp -o data.exe -O2");
    system("g++ mine.cpp -o mine.exe -O2");
    system("g++ std.cpp -o std.exe -O2");

    int awa=0;
    while(233) {
        cout<<++awa<<"\n";

        system("data.exe > in");
        system("std.exe < in > std");
        system("mine.exe < in > mine");

        if(system("fc mine std /w > nul")) {cout<<"Wrong Answer\n";return 0;}
        else cout<<"Accept\n";
    }
}

linux下的,usleep单位是微秒,sleep是秒(但不知打为啥往sleep里面塞小数没用)


#include<bits/stdc++.h>
using namespace std;
int main()
{
    system("g++ data.cpp -o data.exe -O2 -DMudrock") ;
    system("g++ mine.cpp -o mine.exe -O2 -DMudrock") ;
    system("g++ std.cpp -o std.exe -O2 -DMudrock") ;

    int cnt = 0 ;
    while(true) {
        cout << (++cnt) << ": " ;

        system("./data.exe > in");
        system("./std.exe < in > std");
        system("./mine.exe < in > mine");

        if(system("diff mine std -B -w")) return cout << "Wrong Answer\n" , 0 ;
        else cout<<"Accept\n";
    }
}

小工具

Windows

编译运行

#include<bits/stdc++.h>
using namespace std;
int main()
{
    system("g++ awa.cpp -o awa.exe -std=c++14 -O2 -Wl,--stack=256000000 -DMudrock");
    system("awa.exe < in > out");
}

比较

#include<bits/stdc++.h>
using namespace std;
int main()
{
    system("g++ awa.cpp -o awa.exe -O2 -Wl,--stack=256000000");
    system("awa.exe < example > out");
    if(system("fc out ans /w")) cout<<"Wrong Answer\n";
    else cout<<"Accept\n";
}

一键测样例

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

void solve1() {
    string s;cin>>s;
    int l,r; cin>>l>>r;
    for(int i=l;i<=r;i++)
    {
        string sin=s+to_string(i)+".in",sout=s+to_string(i)+".ans";
        string ss="awa.exe < "+sin+" > out";
        system(ss.c_str());
        ss="fc out "+sout+" /w";
        if(system(ss.c_str())) {
            cout<<"Wrong Answer "<<i<<endl;return ;
        }
    }
    cout<<"Accept\n";
}

void solve2() {
    string s; cin >> s;
    string sin=s+".in",sout=s+".ans";
    string ss="awa.exe < "+sin+" > out";
    system(ss.c_str());
    ss="fc out "+sout+" /w";
    if(system(ss.c_str())) cout<<"Wrong Answer "<<endl;
    else cout<<"Accept\n";
}

int main()
{
    system("g++ awa.cpp -o awa -O2 -Wl,--stack=25600000 -DMudrock");
    int opt ; cin >> opt ;
    if(opt==1) solve1(); else solve2();
}

Linux

编译运行

#include<bits/stdc++.h>
using namespace std;
int main()
{
    system("g++ awa.cpp -o awa -O2 -std=c++14 -DMudrock -lm -Wall -fsanitize=address,undefined");
    system("awa.exe < in > out");
}

比较

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string sin=".in",sout=".ans",s; cin>>s;
    system("g++ awa.cpp -o awa -O2 -Wall -std=c++14 -lm -DMudrock -fsanitize=address,undefined");
    system(("time ./awa < "+ s+sin +" > out").c_str());
    if(system(("diff out "+s+sout+" -B -w").c_str())) cout << "Wrong Answer\n";
    else cout << "Accept\n";
}
快读
constexpr auto SIZE(1<<20);
char in[SIZE],out[SIZE],*p1=in,*p2=in,*p3=out;
#define getchar() (p1==p2&&(p2=(p1=in)+fread(in,1,SIZE,stdin),p1==p2)?EOF:*p1++)
#define flush() (fwrite(out,1,p3-out,stdout))
#define putchar(x) (p3==out+SIZE&&(flush(),p3=out),*p3++=(x))
class Flush{public:~Flush(){flush();}}_;
inline int read(){
    int x(0);bool f(0);char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar()) f^=ch=='-';
    for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
    return f?x=-x:x;
}
inline void write(int x){
    x<0?x=-x,putchar('-'):0;static short Sta[50],top(0);
    do{Sta[++top]=x%10;x/=10;}while(x);
    while(top) putchar(Sta[top--]|48);
    putchar('\n');
}

链接

\(memset\)

\(set\)

\(auto\)

\(容斥原理\)

数学

逆元

快速幂

费马小定理 , 仅限 \(mod\) 为素数

inline int inv(int x,int t=mod-2) {
    int ans = 1 ; while(t) {
        if(t&1) Mul(ans,x) ;
        t >>= 1 ; Mul(x,x) ;
    } return ans ;
}
exgcd

int exgcd(int a,int b,int &x,int &y) {
    if(!b) {
        x=1; y=0;
        return a;
    }
    int ans=exgcd(b,a%b,x,y);
    int c=x;
    x=y;
    y=c-a/b*y;
    return ans;
}

int inv(int a,int mod) {
    int x,y;
    exgcd(a,mod,x,y);
    return x>0 ? x : x+mod;
}

递推

inv[n]=power(n,mod-2); for(int i=n-1;i;i--) inv[i]=mul(inv[i+1],i+1);

inv[1]=1; for(int i=2;i<mod;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;

组合数

A , C , lucas

inline int C(int n,int m) {
    if(n<m) return 0; if(!n||!m) return 1;
    return mul(fac[n],inv(mul(fac[m],fac[n-m])));
}

int lucas(int n,int m) {
    if(m==0) return 1;
    return C(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}

inline int A(int n,int m) {
    if(!n||!m) return 1;
    return mul(fac[n],inv(fac[n-m]));
}

exlucas

int A[1010],B[1010];

int exgcd(int a,int b,int &x,int &y) {
    if(!b) {
        x=1;y=0;
        return a;
    }
    int ans=exgcd(b,a%b,x,y);
    int c=x;
    x=y;
    y=c-a/b*y;
    return ans;
}
int inv(int a,int mod) {
    int x,y;
    exgcd(a,mod,x,y);
    return x>0?x:x+mod;
}
int power(int n,int k,int mod) {
    int ans=1;
    while(k) {
        if(k&1) ans=ans*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return ans;
}

int work1(int n,int p,int d) {
    if(!n) return 1;
    int a=1,b=1;
    for(int i=1;i<=p;i++)
        if(i%d) a=a*i%p;
    a=power(a,n/p,p);
    for(int i=p*(n/p);i<=n;i++)
        if(i%d) b=b*(i%p)%p;

    return work1(n/d,p,d)*a%p*b%p;
}

int work0(int n,int d) {
    if(n<d) return 0;
    return work0(n/d,d)+(n/d);
}

int work(int n,int m,int p,int d) {
    int a=work1(n,p,d);
    int b=inv(work1(m,p,d),p);
    int c=inv(work1(n-m,p,d),p);
    int pow=power(d,(work0(n,d)-work0(m,d)-work0(n-m,d)),p);
    return a*b%p*c%p*pow%p;
}

int exlucas(int a,int b,int mod) {
    int tot=0;
    int qwq=mod;
    for(int i=2;i<=sqrt(mod);i++) {
        int awa=1;
        while(!(qwq%i)) {
            awa*=i;
            qwq/=i;
        }
        if(awa>1) {
            A[++tot]=awa;
            B[tot]=work(a,b,awa,i);
        }
    }
    if(qwq>1) {
        A[++tot]=qwq;
        B[tot]=work(a,b,qwq,qwq);
    }

    int ans=0;
    for(int i=1;i<=tot;i++) {
        int awa=mod/A[i];
        int v=inv(awa,A[i]);
        ans=(ans+B[i]*awa%mod*v%mod)%mod;
    }

    return ans%mod;
}

中国剩余定理

crt
    int  x=0,n,m=1;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
        m*=a[i];
    }

    for(int i=1;i<=n;i++) {
        int qwq=m/a[i];
        int v=inv(qwq,a[i]);
        x=(x+b[i]*qwq%m*v%m)%m;
    }
    cout<<x%m;

excrt

    int n,x,y,m,k,ans;
    while(cin>>n) {
        bool pd=false;
        for(int i=1;i<=n;i++)
            cin>>a[i]>>b[i];  

        m=a[1];ans=b[1];
        for(int i=2;i<=n;i++) {
            int gcd=exgcd(m,a[i],x,y);
            int c=((b[i]-ans)%a[i]+a[i])%a[i] ;
            int qwq=a[i]/gcd;
            if(c%gcd) {
                cout<<-1<<endl;
                pd=true;
                break;
            }
            x=x*(c/gcd)%qwq;
            ans+=x*m;
            m*=qwq;
            ans=ans>0?ans:ans+m;
        }
        if(!pd) cout<<(ans>0?ans%m:ans+m)<<endl;
    }

素数相关

判素数

#include<bits/stdc++.h>
using namespace std;
    
int main()
{
    std::ios::sync_with_stdio(false);
    std:cin.tie() ;

    int n,m;
    cin>>n;
    for(int i=2;i<=sqrt(n);i++)
        if(!(n%i)) {
            cout<<"NO \n"<<i<<endl;
            return 0;
        }
    cout<<"YES"<<endl;
}

质因数分解

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;

signed main()
{
    ios::sync_with_stdio(false); cin.tie(); cout.tie();

    int n ; cin >> n ;
    for(int i=2;i*i<=n;i++) {
        while(!(n%i)) {
            n/=i; cout << i << endl ;
        }
    } if(n!=1) cout << n << endl ;
}

欧拉筛

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

const int MAX=1e7+50;

int n,tot,prime[MAX];
bool vis[MAX];

int main()
{
    cin>>n;
    for(int i=2;i<=n;i++) {
        if(!vis[i]) prime[++tot]=i;
        for(int j=1;j<=tot&&prime[j]*i<=n;j++)
        {
            vis[i*prime[j]]=true;
            if(!(i%prime[j])) break;
        }
    }
}

不会分类

线筛 $\mu$
int prime[MAX],mu[MAX],tot;
bool vis[MAX];

void ycl()
{
    mu[1]=1;
    for(int i=2;i<=MMAX;i++)
    {
        if(!vis[i]) {prime[++tot]=i;mu[i]=-1;}
        for(int j=1;j<=tot&&prime[j]*i<=MMAX;j++)
        {
            vis[prime[j]*i]=true;
            if(!(i%prime[j])) {mu[prime[j]*i]=0;break;}
            mu[prime[j]*i]=-mu[i];
        }
    }
}
狄利克雷前缀和
    // 前缀和 f*1
    for(int i=1;i<=tot;i++)
        for(int j=1;prime[i]*j<=MMAX;j++)
            f[prime[i]*j]+=f[j];
    // 后缀和
    for(int i=1;i<=tot;i++)
        for(int j=MMAX/prime[i];j;j--)
            f[j]+=f[prime[i]*j];
    // 前缀差 f*mu
    for(int i=1;i<=tot;i++)
        for(int j=MMAX/prime[i];j;j--)
            f[prime[i]*j]-=f[j];
    // 后缀差
    for(int i=1;i<=tot;i++)
        for(int j=1;prime[i]*j<=MMAX;j++)
            f[j]-=f[prime[i]*j];
正整数自然数幂和
namespace Lagrange {
    int ycl[Max],fac[Max] ;
    int solve(int n,int k)
    {
        for(int i=1;i<=k+2;i++) ycl[i] = add ( power(i,k) , ycl[i-1] ) ;
        if(n<=k+2) return ycl[n] ;
        fac[0] = 1 ; for(int i=1;i<=k+2;i++) fac[i] = mul(fac[i-1],i) ;
        int ans = 0 , fir = 1 ;
        for(int i=1;i<=k+2;i++) Mul(fir,(n-i)) ;
        for(int i=1;i<=k+2;i++) {
            int mem = mul ( mul ( ycl[i] , fir ) , inv ( mul( fac[i-1] , mul( fac[k+2-i] , (n-i) ) ) ) ) ;
            if((k+2-i)&1) Del(ans,mem) ; else Add(ans,mem) ;
        }
        return ans ;
    }
}

高精度

初始化

#define alen a.awa[0]
#define blen b.awa[0]
#define slen s.awa[0]

const int base=10000;

struct _int {
    int awa[20000];
    _int() {memset(awa,0,sizeof(awa));awa[0]=1;}
};

int power[4]={1,10,100,1000};
void icin(_int &a)
{
    string b;
    cin>>b;
    alen=(b.size()-1)/4+1;
    int awa=0;
    for(int i=b.size()-1;i>=0;i--,awa%=4)
        a.awa[(b.size()-i-1)/4+1]+=(b[i]-48)*power[awa++];
    return ;
}

void icout(const _int a)
{
    printf("%d",a.awa[alen]);
    for(int i=alen-1;i>=1;i--)
        printf("%04d",a.awa[i]);
    printf("\n");
    return ;
}

bool operator < (const _int a,const _int b)
{
    if(alen!=blen) return alen<blen;
    for(int i=alen;i>=1;i--)
        if(a.awa[i]!=b.awa[i]) return a.awa[i]<b.awa[i];
    return false;
}

void operator << (_int &a,int b)
{
    for(int i=alen;i>=1;i--)
        a.awa[i+b]=a.awa[i];
    for(int i=b;i>=1;i--)
        a.awa[i]=0;
    alen+=b;
    while(!a.awa[alen]&&alen>1) alen--;
    return ;
}

高精 && 高精

_int operator + (const _int a,const _int b)
{
    _int s;
    slen=max(alen,blen);
    int v=0;
    for(int i=1;i<=max(alen,blen);i++)
    {
        s.awa[i]=a.awa[i]+b.awa[i]+v;
        v=s.awa[i]/base;
        s.awa[i]%=base;
    }
    if(v) s.awa[++slen]=v;
    return s;
}

_int operator - (const _int a,const _int b)
{
    _int s;
    slen=alen;
    int v=0;
    for(int i=1;i<=alen;i++)
    {
        s.awa[i]=a.awa[i]-b.awa[i]-v;
        if(s.awa[i]<0)
            s.awa[i]+=base,v=1;
        else v=0;
    }
    while(slen>1&&!s.awa[slen]) slen--;
    return s;
}

_int operator * (const _int a,const _int b)
{
    _int s;
    slen=alen+blen;
    for(int i=1;i<=alen;i++)
    {
        int v=0;
        for(int j=1;j<=blen;j++)
        {
            s.awa[i+j-1]+=a.awa[i]*b.awa[j]+v;
            v=s.awa[i+j-1]/base;
            s.awa[i+j-1]%=base;
        }
        s.awa[i+blen]+=v;
    }
    while(slen>1&&!s.awa[slen]) slen--;
    return s;
}

_int operator / (const _int a,const _int b)
{
    _int s,v;
    slen=alen;
    for(int i=alen;i>=1;i--)
    {
        v<<1;
        v.awa[1]=a.awa[i];
        while(!(v<b))
        {
            v=v-b;
            s.awa[i]++;
        }
    }
    while(slen>1&&!s.awa[slen]) slen--;
    return s;
}

_int operator % (const _int a,const _int b)
{
    _int v;
    for(int i=alen;i>=1;i--)
    {
        v<<1;
        v.awa[1]=a.awa[i];
        while(!(v<b)) v=v-b;
    }
    return v;
}

高精 && 低精

_int operator *(const _int a,const int b) {
    int i=1,v=0;
    _int ans;
    for(i=1;i<=alen;i++) {
        ans.awa [i]+=a.awa [i]*b+v;
        v=ans.awa [i]/base;
        ans.awa[i]%=base;
    }
    ans.awa [i]=v;
    i=alen+2;
    while(!ans.awa [i]&&i>1) i--;
    ans.awa [0]=i;
    return ans;
}

_int operator /(const _int a,const int b) {
    _int ans;
    int v=0;
    for(int i=alen;i>=1;i--) {
        v*=base;
        v+=a.awa[i];
        ans.awa[i]=v/b;
        v=v-ans.awa[i]*b;
    }
    slen=alen;
    while(!ans.awa[slen]&&slen>1) slen--;
    icout(ans);
    return ans;
}

int operator %(const _int a,const int b) {
    int v=0;
    for(int i=alen;i>=1;i--) {
        v*=base;
        v+=a.awa[i];
        v%=b;
    }
    return v;
}

图论

杂项

倍增LCA

lg[1]=0;
for(int i=2;i<=n;i++)
    lg[i]=lg[i>>1]+1;

int kfa(int u, int step){
    for (int i=0;i<=lg[step];i++)
        if (step >> i & 1) u = fa[u][i];
    return u;
}

for(int i=1;i<=lg[dep[x]];i++)
    fa[x][i]=fa[fa[x][i-1]][i-1];

inline int LCA(int x,int y) {
    if(dep[x]<dep[y]) swap(x,y);
    while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]];
    if(x==y) return x ;
    for(int i=lg[dep[x]];i>=0;i--)
        if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}

RMQ 求 LCA

int lg[MAX],ST[MAX][22],dfn[MAX],dfn_tot;

lg[1]=0;
for(int i=2;i<=n;i++)
    lg[i]=lg[i>>1]+1;

int smax(int x,int y) {return dfn[x]<dfn[y] ? x : y;}
int LCA(int x,int y)
{
    if(x==y) return x;
    if( (x=dfn[x]) > (y=dfn[y]) ) swap(x,y);
    int k=lg[y-x++];
    return smax(ST[x][k],ST[y-(1<<k)+1][k]);
}

dfn[x]=++dfn_tot;
ST[dfn_tot][0]=fat;

for(int j=1;j<=20;j++)
    for(int i=1;i+(1<<j)-1<=n;i++)
        ST[i][j]=smax(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);

最短路

dijkstra
priority_queue<pii,vector<pii>,greater<pii>> q;
int dis[MAX];
bool vis[MAX];
void solve(int root)
{
    memset(dis,0x7f,sizeof(dis));
    dis[root]=0; q.push({dis[root],root});
    while(!q.empty()) {
        auto k=q.top(); q.pop();
        if(vis[k.second]) continue; 
        vis[k.second]=true;
        for(int i=head[k.second];i;i=e[i].nxt) {
            int v=e[i].to;
            if(!vis[v]&&dis[v]>dis[k.second]+e[i].w) {
                dis[v]=dis[k.second]+e[i].w;
                q.push({dis[v],v});
            }
        }
    }
}


关于对 priority_queue 的重载:
    struct point{
        int from,w;
        bool operator <(const point &a) const {
            return w>a.w;
        }
    };
    priority_queue默认是从大到小
    此处对 < 重载 ,w > a.w 时为真
        故当 w > a.w 时 < 成立 ,即 node < (node) a
        即为 node(a) 在 node 之前
        实质上就是 w 小的时候 node 排在前

SPFA

关于SPFA

int dis[MAX];
bool vis[MAX];
queue<int> q;
void SPFA(int root)
{
    dis[root]=0; q.push(root); vis[root]=true;
    while(!q.empty()) {
        int u=q.front(); q.pop();
        for(int i=head[u];i;i=e[i].nxt) {
            int v=e[i].to;
            if(dis[v]>dis[u]+e[i].w) {
                dis[v]=dis[u]+e[i].w;
                if(!vis[v]) q.push(v),vis[v]=true;
            }
        } vis[u]=false;
    }
}

\(vis\) 数组判断是否在队列中,每次松弛将所有不在队列中的点加入队列中

最小生成树

Kruskal

稀疏图用


int fa[MAX];
int from(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=from(fa[x]);
}

struct EDGE{
    int from,to,w;
    bool operator < (const EDGE &a) const {
        return w < a.w ;
    };
}e[EMAX];

int kurs() {
    int ans=0,tot=0;
    iota(fa+1,fa+n+1,1);
    sort(e+1,e+m+1);
    for(int i=1;i<=m;i++)
    {
        if(from(e[i].from)==from(e[i].to))
            continue;
        fa[from(e[i].from)]=e[i].to;
        tot++;
        ans+=e[i].w;
        if(tot==n-1) return ans;
    }
    return -1;
}

Prim

稠密图用


struct EDGE{
    int to,w,next,from;
    bool operator < (const EDGE &a) const {
        return w > a.w;
    }
}e[EMAX*2];
priority_queue<EDGE> q;

int Prim() {
    int awa=1;
    vis[1]=true;
    do {
        for(int i=head[awa];i;i=e[i].next)
            if(!vis[e[i].to]) q.push(e[i]);
        while(vis[q.top().to]&&!q.empty())
            q.pop();
        if(!q.empty()) {
            awa=q.top().to;
            vis[awa]=true;
            ans+=q.top().w;
        }
    } while(!q.empty());
    for(int i=1;i<=n;i++)
        if(!vis[i]) return -1;
    return ans;
}


Prim算法正确性证明:
    对于图中任意一个连通子图,与外界连接的最短边一定是最小生成树中的一条边
以任意一个点为最初的连通块,选出联通块内与外界联通的最短的一条边加入最小生成树中,并将所连接的点加入此连通块

网络流

二分图定理相关

最大匹配数 = 最小点覆盖 = n - 最大独立集

最大匹配数 : 能连上的最多边数 , 且对于任意一个 \(i\) 保证 \(d_i \le 1\)

最小点覆盖 : 选出最少点使得任意一条边至少有一个端点被选中

最大独立集 : 选中任意两点不相连

EK
int mmin[MAX],pre[MAX];
queue<int> q;
int BFS(int s,int t) 
{
    memset(pre,0,sizeof(pre));
    memset(mmin,0x3f,sizeof(mmin));
    q.push(s);
    while(!q.empty())
    {
        int x=q.front(); q.pop();
        for(int i=head[x];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(pre[v]||v==s||!e[i].w) continue;
            pre[v]=i; q.push(v); mmin[v]=min(mmin[x],e[i].w);
        }
    }
    if(!pre[t]) return -1;
    return mmin[t];
}

int solve(int s,int t)
{
    int ans = 0 ;
    while(233) {
        int k = BFS(s,t);
        if(k==-1) break;
        int now = t;
        ans += k;
        while(now!=s) {
            e[pre[now]].w-=k; e[pre[now]^1].w+=k;
            now = e[pre[now]^1].to ;
        }
    }
    return ans ;
}
Dinic
namespace Dinic
{
    int now[MAX],dep[MAX],s,t,ans;
    queue<int> q;

    bool BFS()
    {
        memset(dep,0,sizeof(dep)) ;
        memcpy(now,head,sizeof(head)) ;
        q.push(s) ; dep[s] = 1 ;
        while(!q.empty())
        {
            int x = q.front() ; q.pop() ;
            for(int i=head[x];i;i=e[i].nxt)
            {
                int v = e[i].to ;
                if(dep[v]||!e[i].w) continue ;
                dep[v] = dep[x] + 1 ;
                q.push(v) ;
            }
        }
        return dep[t] ;
    }

    int DFS(int x,int res)
    {
        if(x==t) return res ;
        int sum = 0 ;
        for(int i=now[x];i&&res;i=e[i].nxt)
        {
            now[x] = i ; int v = e[i].to ;
            if(dep[v]!=dep[x]+1||!e[i].w) continue ;
            int k = DFS(v,min(res,e[i].w)) ;
            if(!k) dep[v] = 0 ;
            e[i].w -= k ; e[i^1].w += k ;
            sum += k ; res -= k ;
        }
        return sum ;
    }

    int solve(int S,int T)
    {
        s = S ; t = T ;
        int ans = 0 ;
        while(BFS()) ans += DFS(s,inf) ;
        return ans ;
    }
}
EK费用流
namespace EK_cost
{
    int pre[MAX],dis[MAX];
    bool vis[MAX];
    queue<int> q;

    bool SPFA(int s,int t)
    {
        memset(pre,0,sizeof(pre));
        memset(dis,0x3f,sizeof(dis));

        dis[s]=0; q.push(s); vis[s]=true;

        while(!q.empty()) {
            int u=q.front(); q.pop();
            for(int i=head[u];i;i=e[i].nxt) {
                if(!e[i].flow) continue;
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].w) {
                    dis[v]=dis[u]+e[i].w; pre[v]=i;
                    if(!vis[v]) q.push(v),vis[v]=true;
                }
            } vis[u]=false;
        }
        if(!pre[t]) return false;
        return true;
    }

    pii solve(int s,int t)
    {
        pii ans = {0,0} ;
        while(SPFA(s,t)) {
            int now = t , mmin = inf ;
            
            while(now!=s) {
                mmin=min(mmin,e[pre[now]].flow);
                now=e[pre[now]^1].to;
            } now=t; 
            ans.first+=mmin; ans.second+=mmin*dis[t];

            while(now!=s) {
                e[pre[now]].flow -= mmin; e[pre[now]^1].flow += mmin;
                now = e[pre[now]^1].to ;
            }
        }

        return ans ;
    }
}
zkw 费用流
namespace Dinic_cost
{
    int dis[MAX],now[MAX],s,t ;
    bool vis[MAX] ;
    queue<int> q ;

    bool SPFA()
    {
        memset(dis,0x3f,sizeof(dis)) ;
        memcpy(now,head,sizeof(head)) ;

        q.push(s) ; vis[s] = true ; dis[s] = 0 ;
        while(!q.empty())
        {
            int u = q.front() ; q.pop() ;
            for(int i=head[u];i;i=e[i].nxt) {
                int v = e[i].to ;
                if(!e[i].flow) continue ;
                if(dis[u]+e[i].w<dis[v]) {
                    dis[v] = dis[u] + e[i].w ;
                    if(!vis[v]) q.push(v) , vis[v] = true ;
                }
            } vis[u] = false ;
        }
        return dis[t]!=dis[0] ;
    }

    int DFS(int x,int res)
    {
        if(x==t) return res ;
        int sum = 0 ; vis[x] = true ;
        for(int i=now[x];i&&res;i=e[i].nxt) {
            int v = e[i].to ; now[x] = i ;
            if(vis[v]||!e[i].flow||dis[v]!=dis[x]+e[i].w) continue ;
            int k = DFS(v,min(res,e[i].flow)) ;
            sum += k ; res -= k ;
            e[i].flow -= k ; e[i^1].flow += k ;
        } vis[x] = false ; return sum ;
    }

    pii solve(int S,int T)
    {
        s = S ; t = T ; pii ans = {0,0} ;
        while(SPFA()) {
            int k = DFS(s,inf) ;
            ans.first += k ;
            ans.second += k * dis[t] ;
        }
        return ans ;
    }
}

数据结构

树状数组
struct BIT {
    int num[MAX],n;
    inline int lowbit(int x) { return x&(-x); }
    inline void add(int x,int k) { while(x<=n) num[x]+=k,x+=lowbit(x); }
    inline int check(int x ) { int ans=0; while(x) ans+=num[x],x-=lowbit(x); return ans; }
    inline int find(int l,int r) { return check(r)-check(l-1); }
}bit;
线段树(加乘懒标记)
struct Stree {
    #define lson (x<<1)
    #define rson (x<<1|1)
    #define mid ((l+r)>>1)

    int num[MAX*4];
    int lazt_add[MAX*4],lazt_mul[MAX*4];

    void update(int x) { num[x]=add(num[lson],num[rson]); }

    void pushdown(int x,int l,int r) {
        if(lazt_mul[x]!=1) {
            Mul(lazt_mul[lson],lazt_mul[x]);
            Mul(lazt_mul[rson],lazt_mul[x]);
            Mul(num[lson],lazt_mul[x]); Mul(num[rson],lazt_mul[x]);
            Mul(lazt_add[lson],lazt_mul[x]);
            Mul(lazt_add[rson],lazt_mul[x]);
            lazt_mul[x]=1;
        } 
        if(lazt_add[x]!=0) {
            Add(num[lson],mul(mid-l+1,lazt_add[x]));
            Add(num[rson],mul(r-mid,lazt_add[x]));
            Add(lazt_add[lson],lazt_add[x]);
            Add(lazt_add[rson],lazt_add[x]);
            lazt_add[x]=0;
        }
    }

    void build(int x,int l,int r) 
    {
        lazt_add[x]=0; lazt_mul[x]=1;
        if(l==r) {num[x]=sta[l];return ;}
        build(lson,l,mid); build(rson,mid+1,r);
        update(x);
    }

    void t_add(int x,int l,int r,int tl,int tr,int k) 
    {
        if(l>tr||r<tl) return ;
        if(l>=tl&&r<=tr) { Add(num[x],mul(r-l+1,k)); Add(lazt_add[x],k); return ; }
        pushdown(x,l,r);
        t_add(lson,l,mid,tl,tr,k); t_add(rson,mid+1,r,tl,tr,k);
        update(x);
    }

    void t_mul(int x,int l,int r,int tl,int tr,int k)
    {
        if(l>tr||r<tl) return ;
        if(l>=tl&&r<=tr) { Mul(num[x],k); Mul(lazt_add[x],k); Mul(lazt_mul[x],k); return ; }
        pushdown(x,l,r);
        t_mul(lson,l,mid,tl,tr,k); t_mul(rson,mid+1,r,tl,tr,k);
        update(x);
    }

    int find(int x,int l,int r,int tl,int tr) 
    {
        if(l>tr||r<tl) return 0;
        if(l>=tl&&r<=tr) return num[x];
        pushdown(x,l,r);
        return add( find(lson,l,mid,tl,tr) , find(rson,mid+1,r,tl,tr) );
    }

    #undef lson
    #undef rson
    #undef mid
}tree;

权值线段树(LJJ代码)
struct Stree{
    #define lson ls[x]
    #define rson rs[x]
    #define mid ((l+r)>>1)
    
    int tot=0;
    int num[MAX*50],ls[MAX*50],rs[MAX*50];
    double sum[MAX*50];
    Stree() {
        memset(num,0,sizeof(num));
        memset(ls,0,sizeof(ls));
        memset(rs,0,sizeof(rs));
        memset(sum,0,sizeof(sum));
    }

    void add(int &x,int l,int r,int t,int k) 
    {
        if(!x) x=++tot;
        if(l==r) {num[x]+=k;sum[x]=log(l)*(double)num[x];return ;}
        if(t<=mid) add(lson,l,mid,t,k);
        else add(rson,mid+1,r,t,k);
        num[x]=num[lson]+num[rson]; sum[x]=sum[lson]+sum[rson];
    }

    int merge(int x,int y,int l,int r)
    {
        if(!x||!y) return x+y;
        if(l==r) return (num[x]+=num[y],sum[x]+=sum[y],x);
        lson=merge(ls[x],ls[y],l,mid);
        rson=merge(rs[x],rs[y],mid+1,r);
        num[x]=num[lson]+num[rson]; sum[x]=sum[lson]+sum[rson];
        return x;
    }

    int clear_min(int &x,int l,int r,int t)
    {
        if(!x||l>=t) return 0;
        if(r<t) {int k=num[x];x=0;return k;}
        return clear_min(lson,l,mid,t)+clear_min(rson,mid+1,r,t);
    }

    int clear_max(int &x,int l,int r,int t)
    {
        if(!x||r<=t) return 0;
        if(l>t) {int k=num[x];x=0;return k;}
        return clear_max(lson,l,mid,t)+clear_max(rson,mid+1,r,t);
    }

    int check(int x,int l,int r,int t)
    {
        if(l==r) return l;
        if(num[lson]>=t) return check(lson,l,mid,t);
        else return check(rson,mid+1,r,t-num[lson]);
    }

    #undef lson
    #undef rson
    #undef mid
}tree;

clear_min/max 没有更新值是因为该题目中后面会接一个 add , 后面更新值就可以了

连边后记得用并查集找根 , 否则会出现 a->b , b->c 但 ac 不相连的问题

树链剖分
int son[MAX],siz[MAX],fa[MAX],dep[MAX];
void dfs1(int x,int fat)
{
    son[x]=0; siz[x]=1; fa[x]=fat; dep[x]=dep[fat]+1;
    for(int v:vec[x]) {
        if(v==fat) continue;
        dfs1(v,x);
        siz[x]+=siz[v];
        son[x]=siz[v]>siz[son[x]]?v:son[x];
    }
}

int mp[MAX],dfn[MAX],top[MAX],dfn_num;
void dfs2(int x,int fat)
{
    top[x]=fat; mp[dfn[x]=++dfn_num]=x;
    if(son[x]) dfs2(son[x],fat);
    for(int v:vec[x]) {
        if(dfn[v]) continue;
        dfs2(v,v);
    }
}

struct Stree {
    #define lson (x<<1)
    #define rson (x<<1|1)
    #define mid ((l+r)>>1)

    int num[MAX*4],lazt[MAX*4];

    void pushdown(int x,int l,int r)
    {
        if(!lazt[x]) return ;
        Add(lazt[lson],lazt[x]); Add(lazt[rson],lazt[x]);
        Add(num[lson],mul(lazt[x],(mid-l+1)));
        Add(num[rson],mul(lazt[x],(r-mid)));
        lazt[x]=0;
    }

    void build(int x,int l,int r)
    {
        if(l==r) {num[x]=sta[mp[l]]%mod;return ;} 
        build(lson,l,mid); build(rson,mid+1,r);
        num[x]=::add(num[lson],num[rson]);
    }

    void add(int x,int l,int r,int tl,int tr,int k)
    {
        if(l>tr||r<tl) return ;
        if(l>=tl&&r<=tr) { Add(num[x],mul(k,(r-l+1))); Add(lazt[x],k); return; }
        pushdown(x,l,r);
        add(lson,l,mid,tl,tr,k); add(rson,mid+1,r,tl,tr,k);
        num[x]=::add(num[lson],num[rson]);
    }

    int find(int x,int l,int r,int tl,int tr)
    {
        if(l>tr||r<tl) return 0;
        if(l>=tl&&r<=tr) return num[x];
        pushdown(x,l,r);
        return ::add(find(lson,l,mid,tl,tr),find(rson,mid+1,r,tl,tr));
    }

    #undef lson
    #undef rson
    #undef mid
}tree;

int n;

void spadd(int x,int y,int w) 
{
    while(top[x]!=top[y]) {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        tree.add(1,1,n,dfn[top[x]],dfn[x],w);
        x=fa[top[x]];
    }
    if(dfn[x]>dfn[y]) swap(x,y);
    tree.add(1,1,n,dfn[x],dfn[y],w);
}

int spfind(int x,int y) {
    int ans = 0;
    while(top[x]!=top[y]) {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        Add(ans,tree.find(1,1,n,dfn[top[x]],dfn[x]));
        x=fa[top[x]];
    }
    if(dfn[x]>dfn[y]) swap(x,y);
    Add(ans,tree.find(1,1,n,dfn[x],dfn[y]));
    return ans ;
}
可持久化线段树
struct Stree {
    #define lson ls[x]
    #define rson rs[x]
    #define mid ((l+r)>>1)

    int tot;
    int num[MAX*100],ls[MAX*100],rs[MAX*100];

    void build(int &x,int l,int r) 
    {
        if(!x) x=++tot;
        if(l==r) {num[x]=sta[l];return ;}
        build(lson,l,mid); build(rson,mid+1,r);
    }

    void copy(int &x) 
    {
        num[++tot]=num[x];
        ls[tot]=ls[x];
        rs[tot]=rs[x];
        x=tot;
    }

    void add(int &x,int l,int r,int t,int k)
    {
        copy(x);
        if(l==r) {num[x]=k;return ;}
        if(t<=mid) add(lson,l,mid,t,k);
        else add(rson,mid+1,r,t,k);
    }

    int find(int x,int l,int r,int t)
    {
        if(l==r) return num[x];
        if(t<=mid) return find(lson,l,mid,t);
        else return find(rson,mid+1,r,t);
    }

    #undef lson
    #undef rson
    #undef mid
} tree ;
主席树
struct Stree {
    #define lson ls[x]
    #define rson rs[x]
    #define mid ((l+r)>>1)

    int tot;    
    int num[MAX*20],ls[MAX*20],rs[MAX*20];

    void copy(int &x) {
        num[++tot]=num[x]; 
        ls[tot]=ls[x]; rs[tot]=rs[x];
        x=tot;
    }

    void add(int &x,int l,int r,int t) 
    {
        copy(x);
        if(l==r) {num[x]++;return ;}
        if(t<=mid) add(lson,l,mid,t);
        else add(rson,mid+1,r,t);
        num[x]=num[lson]+num[rson];
    }

    int check(int x,int y,int l,int r,int k)
    {
        if(l==r) return l;
        if(num[ls[y]]-num[ls[x]]>=k) return check(ls[x],ls[y],l,mid,k);
        else return check(rs[x],rs[y],mid+1,r,k-(num[ls[y]]-num[ls[x]]));
    }

    #undef lson
    #undef rson
    #undef mid
} tree;
树状数组套权值线段树
struct TREE{

    #define lson ls[x]
    #define rson rs[x]
    #define mid ((l+r)>>1)

    int tot;
    int ls[MAX*200],rs[MAX*200],size[MAX*200];

    void csh() {
        tot=0;
        memset(ls,0,sizeof(ls));
        memset(rs,0,sizeof(rs));
        memset(size,0,sizeof(size));
    }

    void add(int &x,int l,int r,int k)
    {
        if(!x) x=++tot;
        if(l==r) {
            size[x]++;
            return ;
        }

        if(k<=mid) add(lson,l,mid,k);
        else add(rson,mid+1,r,k);
        size[x]=size[lson]+size[rson];

        return ;
    }

    void del(int &x,int l,int r,int k)
    {
        if(l==r) {
            if(size[x]==1) x=0;
            else size[x]--;
            return ;
        }

        if(k<=mid) del(lson,l,mid,k);
        else del(rson,mid+1,r,k);
        size[x]=size[lson]+size[rson];

        return ;
    }

    int query(int l,int r,int k)
    {
        if(l==r) return l;

        int tot=0;
        for(int i:tr[pd])
            tot+=size[ls[i]];
        for(int i:tl[pd])
            tot-=size[ls[i]];

        if(k<=tot) {
            tl[!pd].clear();tr[!pd].clear();
            for(int i:tr[pd])
                tr[!pd].push_back(ls[i]);
            for(int i:tl[pd])
                tl[!pd].push_back(ls[i]);
            pd=!pd;
            return query(l,mid,k);
        }
        else {
            tl[!pd].clear();tr[!pd].clear();
            for(int i:tr[pd])
                tr[!pd].push_back(rs[i]);
            for(int i:tl[pd])
                tl[!pd].push_back(rs[i]);
            pd=!pd;
            return query(mid+1,r,k-tot);
        }
    }

    #undef mid

}tree;

inline int lowbit(int x) {return (-x)&x;}

int main()
{
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j+=lowbit(j))
            tree.add(root[j],1,m,awa[i]);

    for(int T=1;T<=t;T++)
    {
        if(q[T].opt=='Q') {
            int l=q[T].c[0],r=q[T].c[1];
            tr[pd].clear();tl[pd].clear();
            for(int i=r;i;i-=lowbit(i))
                tr[pd].push_back(root[i]);
            for(int i=l-1;i;i-=lowbit(i))
                tl[pd].push_back(root[i]);

            cout<<fls[tree.query(1,m,q[T].c[2])]<<endl;
        }
        else {
            int k=q[T].c[0],t=q[T].c[1];
            for(int i=k;i<=n;i+=lowbit(i))
            {
                tree.del(root[i],1,m,awa[k]);
                tree.add(root[i],1,m,t);
            }
            awa[k]=t;
        }
    }
}
平衡树

链接

字符串

hash
const int base=233;

int hs[MAX],power[MAX];
inline int find(int l,int r) {return del(hs[r],mul(hs[l-1],power[r-l+1]));}

power[0]=1; for(int i=1;i<=n;i++) power[i]=mul(power[i-1],base);
for(int i=1;i<=n;i++) hs[i]=add(mul(hs[i-1],base),s[i]);
AC自动机
struct TREE{
    int son[30];
    int fail,num;
    bool end;
}tree[MAX];
int tot,ans;

int build(string s)
{
    int root=0;
    for(int i=0;i<s.size();i++)
    {
        if(!tree[root].son[s[i]-'a'])
            tree[root].son[s[i]-'a']=++tot;
        root=tree[root].son[s[i]-'a'];
    } 
    tree[root].end=true;
    return root;
}

queue<int> q;
void fail_build()
{
    for(int i=0;i<26;i++)
        if(tree[0].son[i]) {
            tree[tree[0].son[i]].fail=0;
            q.push(tree[0].son[i]);
        }

    while(!q.empty())
    {
        int root=q.front();
        q.pop();
        for(int i=0;i<26;i++)
        {
            if(tree[root].son[i]) {
                tree[tree[root].son[i]].fail=tree[tree[root].fail].son[i];
                q.push(tree[root].son[i]);
            }
            else tree[root].son[i]=tree[tree[root].fail].son[i];
        }
    }
}

void find(string s) {
    cin>>s;
    int root=0;
    for(int i=0;i<s.size();i++)
    {
        root=tree[root].son[s[i]-'a'];
        for(int j=root;j;j=tree[j].fail)
        {
            if(tree[j].end) tree[j].num++;
            ans=max(ans,tree[j].num);
        }
    }
}
后缀数组
char s[MAX];
int x[MAX],y[MAX],t[MAX],sa[MAX],hei[MAX];

void Qsort(int n,int m)
{
    for(int i=1;i<=m;i++) t[i]=0;
    for(int i=1;i<=n;i++) t[x[i]]++;
    for(int i=2;i<=m;i++) t[i]+=t[i-1];
    for(int i=n;i>=1;i--) sa[t[x[y[i]]]--]=y[i];
}
void SA(int n)
{
    for(int i=1;i<=n;i++) x[i] = s[i]-'a'+1 ;
    iota(y+1,y+n+1,1);
    int m = 'z'+1 ; Qsort(n,m);

    for(int k=1;k<=n;k<<=1)
    {
        int num = 0;
        for(int i=n-k+1;i<=n;i++) y[++num] = i;
        for(int i=1;i<=n;i++) if(sa[i]>k) y[++num]=sa[i]-k;
        Qsort(n,m); swap(x,y);
        num = x[sa[1]] = 1 ;
        for(int i=2;i<=n;i++)
            x[sa[i]] = (y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
        if(num==n) break; else m = num ;
    }

    for(int i=1,k=0;i<=n;i++)
    {
        if(k) k-- ;
        while(s[i+k]==s[sa[x[i]-1]+k]) k++;
        hei[x[i]] = k ;
    }
}
PAM
namespace PAM
{
    int cnt,last ;
    int son[MAX][26],len[MAX],fail[MAX],size[MAX];
    
    void csh(int n)
    {
        cnt = fail[0] = 1 ;
        len[1] = -1 ;
    }

    int getfail(int k,int now) {
        while(s[k-len[now]-1]!=s[k]) now = fail[now];
        return now ;
    }

    void insert(int k)
    {
        int c = s[k]-'a' ;
        last = getfail(k,last) ;
        if(!son[last][c]) {
            fail[++cnt] = son[getfail(k,fail[last])][c] ;
            son[last][c] = cnt ;
            len[cnt] = len[last]+2 ;
        }
        last = son[last][c];
        size[last] ++ ;
    }
}
SAM
namespace SAM
{
    int last=1,cnt=1;
    int son[MAX][26],len[MAX],fa[MAX];

    void insert(int c)
    {
        int p = last , np = last = ++cnt ;
        len[np] = len[p] + 1 ;
        for(;p&&!son[p][c];p=fa[p]) son[p][c] = np ;
        if(!p) fa[np] = 1 ;
        else {
            int q = son[p][c] ;
            if(len[q]==len[p]+1) fa[np] = q ;
            else {
                int nq = ++cnt ;
                fa[nq] = fa[q] ;
                memcpy(son[nq],son[q],sizeof(son[q])) ;
                fa[q] = fa[np] = nq ;
                len[nq] = len[p] + 1 ;
                for(;son[p][c]==q;p=fa[p]) son[p][c] = nq ;
            }
        } 
    }
}
posted @ 2022-07-30 10:40  midsu  阅读(304)  评论(6编辑  收藏  举报