火车头:

#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#pragma GCC optimize(2)

高精度:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int a[maxn],b[maxn],res[maxn];
string add(string s1,string s2){
    int n=s1.length(),m=s2.length();
    for(int i=0;i<n;i++)a[i]=s1[n-1-i]-'0';
    for(int i=0;i<m;i++)b[i]=s2[m-1-i]-'0';
    int len=max(n,m)+1;
    for(int i=n;i<len;i++)a[i]=0;
    for(int i=m;i<len;i++)b[i]=0;
    for(int i=0;i<len;i++)res[i]=0;
    for(int i=0;i<len;i++){
        res[i]+=a[i]+b[i];
        if(res[i]>=10){
            res[i+1]+=res[i]/10;
            res[i]%=10;
        }
    }
    int i=len-1;
    while(res[i]==0&&i>0)i--;
    string s="";
    for(;i>=0;i--)s+=(char)(res[i]+'0');
    return s;
}
string sub(string s1,string s2){
    int n=s1.length(),m=s2.length();
    for(int i=0;i<n;i++)a[i]=s1[n-1-i]-'0';
    for(int i=0;i<m;i++)b[i]=s2[m-1-i]-'0';
    int len=max(n,m);
    for(int i=n;i<len;i++)a[i]=0;
    for(int i=m;i<len;i++)b[i]=0;
    for(int i=0;i<len;i++)res[i]=0;
    for(int i=0;i<len;i++){
        res[i]+=a[i]-b[i];
        if(res[i]<0){
            res[i+1] --;
            res[i] += 10;
        }
    }
    int i=len-1;
    while(res[i]==0&&i>0)i--;
    string s="";
    for(;i>=0;i--)s+=(char)(res[i]+'0');
    return s;
}
bool cmp(string s1,string s2){
    int n=s1.length(),m=s2.length();
    int i;
    for(i=0;i<n-1&&s1[i]=='0';i++);
    s1=s1.substr(i);
    for(i=0;i<m-1&&s2[i]=='0';i++);
    s2=s2.substr(i);
    if(s1.length()!=s2.length())return s1.length()<s2.length();
    return s1<s2;
}
string Add(string s1,string s2){
    if(s1[0]=='-'&&s2[0]=='-'){
        return "-"+add(s1.substr(1),s2.substr(1));
    }
    else if(s1[0]=='-'){
        s1=s1.substr(1);
        if(cmp(s1,s2)==true){
            return sub(s2,s1);
        }else{
            return "-"+sub(s1,s2);
        }
    }
    else if(s2[0]=='-'){
        s2=s2.substr(1);
        if(cmp(s1,s2)){
            return "-"+sub(s2,s1);
        }else{
            return sub(s1,s2);
        }
    }
    else{
        return add(s1,s2);
    }
}
string multi(string s1,string s2){
    int n=s1.length(), m=s2.length();
    for(int i=0;i<n;i++)a[i]=s1[n-1-i]-'0';
    for(int i=0;i<m;i++)b[i]=s2[m-1-i]-'0';
    int len=n+m;
    for(int i=n;i<len;i++)a[i]=0;
    for(int i=m;i<len;i++)b[i]=0;
    for(int i=0;i<len;i++)res[i]=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            res[i+j]+=a[i]*b[j];
    for(int i=0;i<len;i++){
        res[i+1]+=res[i]/10;
        res[i]%=10;
    }
    int i=len-1;
    while(res[i]==0&&i>0)i--;
    string s="";
    for(;i>=0;i--)s+=(char)(res[i]+'0');
    return s;
}
string divide(string s1,string s2){
    string s="",t="";
    int n=s1.length(),m=s2.length();
    bool flag=false;
    for(int i=0;i<n;i++){
        s+=s1[i];
        int num=0;
        while(cmp(s,s2)==false){
            num++;
            s=sub(s,s2);
        }
        if(num>0){
            flag=true;
            char c=(char)(num+'0');
            t+=c;
        }
        else if(flag){
            t+='0';
        }
    }
    if(t.length()==0)t="0";
    return t;
}
int main(){
	string s1,s2;
	cin>>s1>>s2;
	cout<<"Add:"+s1+'+'+s2+'='+Add(s1,s2)+'\n';
	cout<<"Sub:"+s1+'-'+s2+'='+Add(s1,'-'+s2)+'\n';
	cout<<"Mul:"+s1+'*'+s2+'='+multi(s1,s2)+'\n';
	cout<<"Div:"+s1+'/'+s2+'='+divide(s1,s2)+'\n';
}

fio快读快输

class fast_iostream{
private:
    const int MAXBF = 1 << 20; FILE *inf, *ouf;
    char *inbuf, *inst, *ined;
    char *oubuf, *oust, *oued;
    inline void _flush(){fwrite(oubuf, 1, oued - oust, ouf);}
    inline char _getchar(){
        if(inst == ined) inst = inbuf, ined = inbuf + fread(inbuf, 1, MAXBF, inf);
        return inst == ined ? EOF : *inst++;
    }
    inline void _putchar(char c){
        if(oued == oust + MAXBF) _flush(), oued = oubuf;
        *oued++ = c;
    }
public:
     fast_iostream(FILE *_inf = stdin, FILE * _ouf = stdout)
    :inbuf(new char[MAXBF]), inf(_inf), inst(inbuf), ined(inbuf),
     oubuf(new char[MAXBF]), ouf(_ouf), oust(oubuf), oued(oubuf){}
    ~fast_iostream(){_flush(); delete inbuf; delete oubuf;}
    template <typename Int>
    fast_iostream& operator >> (Int  &n){
        static char c;
        while((c = _getchar()) < '0' || c > '9');n = c - '0';
        while((c = _getchar()) >='0' && c <='9') n = n * 10 + c - '0';
        return *this;
    }
    template <typename Int>
    fast_iostream& operator << (Int   n){
        if(n < 0) _putchar('-'), n = -n; static char S[20]; int t = 0;
        do{S[t++] = '0' + n % 10, n /= 10;} while(n);
        for(int i = 0;i < t;++i) _putchar(S[t - i - 1]);
        return *this;
    }
    fast_iostream& operator << (char  c){_putchar(c);    return *this;}
    fast_iostream& operator << (const char *s){
        for(int i = 0;s[i];++i) _putchar(s[i]); return *this;
    }
}fio;

普通快读快写

inline long long read()
{
    long long x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
	{
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
	{
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
inline void write(long long x)
{
	if(x==0)
	{
		putchar('0');
		return;
	}
    char F[200];
    long long tmp=x>0?x:-x;
    if(x<0) putchar('-');
    long long cnt=0;
    while(tmp>0)
    {
        F[cnt++]=tmp%10+'0';
        tmp/=10;
    }
    while(cnt>0)putchar(F[--cnt]);
}

组合数

int qzj[20000001],inv[20000001];
long long poww(long long a,long long b)
{
	long long re=1;
	while(b)
	{
		if(b&1)
		{
			re*=a;
			re%=mod; 
		}
		a*=a;
		a%=mod;
		b>>=1;
	} 
	return re;
}
int C(int a,int b)
{
	if(b>a) return 0;
	return 1ll*qzj[a]*inv[a-b]%mod*inv[b]%mod;
}
signed main()
{
	qzj[0]=1;
	for(int i=1;i<=20000000;i++)
	{
		qzj[i]=1ll*qzj[i-1]*i%mod;
	}
	inv[20000000]=poww(qzj[20000000],mod-2);
	for(int i=20000000-1;i>=0;i--)
	{
		inv[i]=1ll*inv[i+1]*(i+1)%mod;
	}
}

模板字典树:

#include<cstdio>
#include<iostream>
#include<map>
#include<vector>
#include<string>
using namespace std;
struct ac
{
    int nxt[27],num;
}ac[1000001];
int n,m,p;
void add(string a)
{
    int P=0;
    for(int i=0;i<a.size();i++)
    {
        int t=a[i]-'a';
        if(!ac[P].nxt[t])
        {
            ac[P].nxt[t]=++p;
        }
        P=ac[P].nxt[t];
    }
    ac[P].num++;
    return;
}
bool serch(string a)
{
    int P=0;
    for(int i=0;i<a.size();i++)
    {
        int t=a[i]-'a';
        if(!ac[P].nxt[t])
        {
            return false;
        }
        P=ac[P].nxt[t];
    }
    return true;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		string a;
		cin>>a;
		add(a);
	}
	for(int i=1;i<=m;i++)
	{
		string a;
		cin>>a;
		printf(serch(a) ? "FIND\n" : "UNFIND\n");
	}
}

分块

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
int n,m,st[250000],ed[250000],sum[250000],a[500001],pos[500001],len,w,ww,ans,opt,l,r,x,tag[250001];
void make()
{
    len=sqrt(n);
    for(int i=1;i*i<=n;i++)
    {
        st[i]=(i-1)*len+1;
        ed[i]=i*len;
        for(int z=st[i];z<=ed[i];z++)
        {
            sum[i]+=a[z];
            pos[z]=i;
        }
    }
    if(len*len!=n)
    {
        st[len+1]=len*len+1;
        ed[len+1]=n;
        for(int z=st[len+1];z<=ed[len+1];z++)
        {
            sum[len+1]+=a[z];
            pos[z]=len+1;
        }
        len++;
    }
}
void add(int l,int r,int x)
{
    w=pos[l];
    ww=pos[r];
    if(ww==w)
    {
        for(int i=l;i<=r;i++)
        {
            a[i]+=x;
            sum[w]+=x;
        }
    }
    else
    {
        for(int i=l;i<st[w+1];i++)
        {
            a[i]+=x;
            sum[w]+=x;
        }
        for(int i=w+1;i<ww;i++)
        {
            sum[i]+=(ed[i]-st[i]+1)*x;
            tag[i]+=x;
        }
        for(int i=ed[ww-1]+1;i<=r;i++)
        {
            a[i]+=x;
            sum[ww]+=x;
        }
    }
}
int get(int l,int r)
{
    int ans;
    w=pos[l];
    ww=pos[r];
    if(ww==w)
    {
        ans=0;
        for(int i=l;i<=r;i++)
        {
            ans+=a[i]+tag[w];
        }
        return ans;
    }
    else
    {
        ans=0;
        for(int i=l;i<st[w+1];i++)
        {
            ans+=a[i]+tag[w];
        }
        for(int i=w+1;i<ww;i++)
        {
            ans+=sum[i];
        }
        for(int i=ed[ww-1]+1;i<=r;i++)
        {
            ans+=a[i]+tag[ww];
        }
        return ans;
    }
}
signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    make();
    for(int i=1,opt,l,r,v;i<=m;i++)
    {
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt==1)
		{
			scanf("%lld",&v);
			add(l,r,v);
		}
		else
		{
			cout<<get(l,r)<<endl;
		}
	}
}

懒标记线段树

#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,sum[4000004],tag[4000004],a,p,x,y,v;
void addtag(long long o,long long l,long long r,long long v)
{
	tag[o]+=v;
	sum[o]+=(r-l+1)*v;
}
void downtag(long long o,long long l,long long r)
{
	if(tag[o]==0) return;
	long long mid=r+l>>1;
	addtag((o<<1),l,mid,tag[o]);
	addtag((o<<1)+1,mid+1,r,tag[o]);
	tag[o]=0;
}
void uptag(long long o)
{
	sum[o]=sum[o<<1]+sum[(o<<1)+1];
}
void add(long long o,long long l,long long r,long long x,long long y,long long v)
{
    if(l>y || r<x)
    {
        return;
    }
    if(x<=l && r<=y)
    {
    	addtag(o,l,r,v);
    	return;
	}
    long long mid=r+l>>1;
    downtag(o,l,r);
    add((o<<1),l,mid,x,y,v);
    add((o<<1)+1,mid+1,r,x,y,v);
    uptag(o);
}
long long get(long long o,long long l,long long r,long long x,long long y)
{
    if(l>y || r<x)
    {
		return 0;	
	}
    if(x<=l && r<=y)
    {
		return sum[o];
	}
    long long mid=l+r>>1;
    downtag(o,l,r);
    return get(o<<1,l,mid,x,y)+get((o<<1)+1,mid+1,r,x,y);
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for(long long i=1;i<=n;i++)
    {
        scanf("%lld",&a);
        add(1,1,n,i,i,a);
    }
    for(long long i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&p,&x,&y);
        if(p&1)
        {
        	scanf("%lld",&v);
			add(1,1,n,x,y,v);
		}
        else
        {
			printf("%lld\n",get(1,1,n,x,y));
		}
    }
}

线段树

#include<iostream>
#include<cstdio>
#define INF 0x7f7f7f
using namespace std;
int n,m,mi[400004],a,p,x,y;
void add(int o,int l,int r,int x,int y)
{
    if(l==r)
    {
        mi[o]=y;
        return;
    }
    int mid=r+l>>1;
    if(x<=mid) add((o<<1),l,mid,x,y);
    else add((o<<1)+1,mid+1,r,x,y);
    mi[o]=min(mi[(o<<1)],mi[(o<<1)+1]);
}
int get(int o,int l,int r,int x,int y)
{
    if(x>r || y<l) return INF;
    if(x<=l&&y>=r) return mi[o];
    int mid=l+r>>1;
    return min(get(o<<1,l,mid,x,y),get((o<<1)+1,mid+1,r,x,y));
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a);
        add(1,1,n,i,a);
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&p,&x,&y);
        if(p&1) printf("%d ",get(1,1,n,x,y));
        else add(1,1,n,x,y);
    }
}

权值线段树:

#include<iostream>
#include<cstdio>
#define INF 0x7f7f7f
using namespace std;
long long n,m,a,p,x,y,ma=-2147483647,mi=2147483647,area=1ll,len=1ll/*此处开1ll会与其他指针重合*/;
struct polo
{
	long long l,r,w;
}sum[4000003];
void add(long long &o,long long l,long long r,long long x,long long v) //插入 
{
	if(!o) o=++len; //新点 
    if(l==r)
    {
        sum[o].w+=v;
        return;
    }
    long long mid=r+l>>1ll;
    if(x<=mid) add((sum[o].l),l,mid,x,v);
    else add(sum[o].r,mid+1ll,r,x,v);
    sum[o].w=sum[(sum[o].l)].w+sum[sum[o].r].w;
}
long long get(long long o,long long l,long long r,long long k) //k出现的次数 
{
    if(l==r) return sum[o].w;
    long long mid=l+r>>1ll;
    return (k<=mid ? get(sum[o].l,l,mid,k) : get(sum[o].r,mid+1ll,r,k));
}
long long find(long long o,long long l,long long r,long long x,long long y) //x-y数的个数
{
	if(!o) return 0;
	if(x>r || y<l) return 0;
    if(x<=l&&y>=r) return sum[o].w;
    long long mid=l+r>>1ll;
    return find(sum[o].l,l,mid,x,y)+find(sum[o].r,mid+1ll,r,x,y);
}
long long fsmall(long long o,long long l,long long r,long long k) //求第k小的数
{
	if(l==r) return l;
	long long mid=l+r>>1ll;
	if(k<=sum[(sum[o].l)].w) return fsmall((sum[o].l),l,mid,k);
	else return fsmall(sum[o].r,mid+1ll,r,k-sum[(sum[o].l)].w);
}
long long fbig(long long o,long long l,long long r,long long k) //求第k大的数
{
	if(l==r) return l;
	long long mid=l+r>>1ll;
	if(k<=sum[sum[o].r].w) return fbig(sum[o].r,mid+1ll,r,k);
	else return fbig((sum[o].l),l,mid,k-sum[sum[o].r].w);
}
long long lowerbound(long long l,long long r,long long k) //前驱 
{
	return fsmall(1ll,l,r,find(1ll,l,r,-10000001,k-1ll));
}
long long upperbound(long long l,long long r,long long k) //后继 
{
	return fsmall(1ll,l,r,find(1ll,l,r,-10000001,k)+1ll);
}
int main()
{
    scanf("%lld",&n);
    for(long long i=1ll,opt;i<=n;i++)
    {
        scanf("%lld%lld",&opt,&a);
        if(opt==1ll)
        {
        	add(area,-10000001,10000001,a,1ll);
		}
		if(opt==2)
		{
			add(area,-10000001,10000001,a,-1ll);
		}
		if(opt==3)
		{
			printf("%lld\n",find(1ll,-10000001,10000001,1ll,a-1ll)+1ll);
		}
		if(opt==4)
		{
			printf("%lld\n",fsmall(area,-10000001,10000001,a));
		}
		if(opt==5)
		{
			printf("%lld\n",lowerbound(-10000001,10000001,a));
		}
		if(opt==6)
		{
			printf("%lld\n",upperbound(-10000001,10000001,a));
		}
    }
}

可持久化权值线段树

#include<iostream>
#include<cstdio>
#define INF 0x7f7f7f
using namespace std;
int n,m,a,ma,root[200001],mi=2147483647,area=1,len=1/*此处开1会与其他指针重合*/;
struct polo
{
	int l,r,w;
}sum[8000001];
void add(int &o,int p,int l,int r,int x,int v) //插入 
{
	o=++len;
	sum[o]=sum[p]; //新点 
    if(l==r)
    {
        sum[o].w+=v;
        return;
    }
    int mid=r+l>>1;
    if(x<=mid) add((sum[o].l),(sum[p].l),l,mid,x,v);
    else add(sum[o].r,sum[p].r,mid+1,r,x,v);
    sum[o].w=sum[(sum[o].l)].w+sum[sum[o].r].w;
}
int get(int o,int l,int r,int k) //k出现的次数 
{
    if(l==r) return sum[o].w;
    int mid=l+r>>1;
    return (k<=mid ? get(sum[o].l,l,mid,k) : get(sum[o].r,mid+1,r,k));
}
int fsmall(int o,int p,int l,int r,int k) //求第k小的数
{
	if(l==r) return l;
	int mid=l+r>>1,fuck=sum[sum[o].l].w-sum[sum[p].l].w;
	if(k<=fuck) return fsmall((sum[o].l),(sum[p].l),l,mid,k);
	else return fsmall(sum[o].r,sum[p].r,mid+1,r,k-fuck);
}
int fsum(int o,int p,int l,int r,int f,int k) //区间值[f,k]的数的个数
{
	if(f<=l&&r<=k)
	{
		return sum[o].w-sum[p].w;
	}
	if(l>k||r<f)
	{
		return 0;
	}
	int mid=r+l>>1;
	return fsum(sum[o].l,sum[p].l,l,mid,f,k)+fsum(sum[o].r,sum[p].r,mid+1,r,f,k);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
    	scanf("%d",&a);
    	add(root[i],root[i-1],-1000000001,1000000001,a,1);
	}
    for(int i=1,l,r;i<=m;i++)
    {
        scanf("%d%d%d",&l,&r,&a);
        printf("%d\n",fsmall(root[r],root[l-1],-1000000001,1000000001,a));
    }
}

dij最短路

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
int n,m,a[10001],u,v,w;
struct edge
{
	int u,v,w;
};
struct point
{
	int id,d;
	bool operator < (point a) const
	{
		return d>a.d;
	}
};
vector <edge> g[10001];
bool vis[10001];
priority_queue<point> q;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v>>w;
		g[u].push_back((edge){u,v,w});
	}
	memset(a,0x7f,sizeof(a));
	a[1]=0;
	q.push((point){1,0});
	while(q.empty()==false)
	{
		int u=q.top().id;
		q.pop();
		vis[u]=true;
		for(int i=0;i<g[u].size();i++)
		{
			int v=g[u][i].v;
			int w=g[u][i].w;
			if(vis[v]) continue;
			if(a[u]+w<a[v])
			{
				a[v]=a[u]+w;
				q.push((point){v,a[v]});
			}
		}
	}
	cout<<a[n];
}

最近公共祖先

#include<iostream>
#include<cstdio>
#include<vector>
#define log 20
using namespace std;
int n,m,k,father[500001][21],deep[500001]; //father[i][j] 表示点i的第2^j个祖先,转移方程:father[i][j]=father[father[i][j-1]][j-1] 
vector <int> g[500001];
void getfather(int u,int fa)
{
	father[u][0]=fa; //初始化
	for(int i=1;i<=log;i++)
	{
		father[u][i]=father[father[u][i-1]][i-1]; //转移 
	}
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==fa) continue;
		getfather(v,u); //向下搜索 
	}
}

void getdeep(int u,int fa)
{
	deep[u]=deep[fa]+1; //统计深度 
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==fa) continue;
		getdeep(v,u);
	}
}

int getlca(int u,int v)
{
	if(deep[u]>deep[v]) swap(u,v); //保证v更深 
    int mul=deep[v]-deep[u],w=0;
    while(mul)
    {
        if(mul&1) v=father[v][w]; //向上跳 
        mul>>=1;
        w++;
    }
    if(u==v) return u;
    for(int i=log;i>=0;i--)
    {
        if(father[u][i]!=father[v][i]) //点不同,则不再一条链上 
        {
            u=father[u][i]; //向上跳 
            v=father[v][i];
        }
    }
    return father[u][0];
}
int main()
{
	scanf("%d",&n);
	for(int i=1,u,v;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	getfather(1,0); //根为1节点
	getdeep(1,0);
	scanf("%d",&m);
	for(int i=1,u,v;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		printf("%d\n",getlca(u,v));
	}
}

重链剖分

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,q,mod,rt,w[1000001],sum[8000001],tag[8000001];
vector<int> g[1000001];
void addtag(int o,int l,int r,int v)
{
    tag[o]+=v%mod;
    tag[o]%=mod;
    sum[o]+=(r-l+1)%mod*v%mod;
	sum[o]%=mod;
}
void downtag(int o,int l,int r)
{
    if(tag[o]==0) return;
    int mid=r+l>>1;
    addtag((o<<1),l,mid,tag[o]);
    addtag((o<<1)+1,mid+1,r,tag[o]);
    tag[o]=0;
}
void uptag(int o)
{
    sum[o]=sum[o<<1]+sum[(o<<1)+1];
	sum[o]%=mod;
}
void add(int o,int l,int r,int x,int y,int v)
{
    if(l>y || r<x)
    {
        return;
    }
    if(x<=l && r<=y)
    {
        addtag(o,l,r,v);
        return;
    }
    int mid=r+l>>1;
    downtag(o,l,r);
    add((o<<1),l,mid,x,y,v);
    add((o<<1)+1,mid+1,r,x,y,v);
    uptag(o);
}
int get(int o,int l,int r,int x,int y)
{
    if(l>y || r<x)
    {
        return 0;   
    }
    if(x<=l && r<=y)
    {
        return sum[o]%mod;
    }
    int mid=l+r>>1;
    downtag(o,l,r);
    return (get(o<<1,l,mid,x,y)+get((o<<1)+1,mid+1,r,x,y))%mod;
}
int fat[100001],siz[100001],dep[100001],hson[100001],top[100001],cnt,dfn[100001],dis[100001];
void getdfsh(int u,int fa) //获取:父节点,深度,子树大小,重儿子 
{
	fat[u]=fa;
	dep[u]=dep[fa]+1;
	int lll=0;
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==fa) continue;
		getdfsh(v,u);
		if(siz[v]>lll)
		{
			hson[u]=v;
			lll=siz[v];
		}
		siz[u]+=siz[v];
	}
	siz[u]++;
}
void gettd(int u,int fa) //获取:链顶,dfs序 
{
	dfn[u] = ++cnt;
	dis[u] = cnt;
	if(hson[fat[u]]==u)
	{
		top[u]=top[fa];
	}
	else
	{
		top[u]=u;
	}
	if(hson[u]!=0) gettd(hson[u],u); //优先重子 
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==fa||v==hson[u]) continue;
		gettd(v,u);
	}
}
int addlsum(int st,int ed,int v) //一条链的和
{
	v%=mod;
	if(dfn[st]<dfn[ed]) swap(st,ed);
	int u=st,re=0;
	while(1)
	{
		if(dfn[top[u]]<=dfn[ed])
		{
			add(1,1,n,dfn[ed],dfn[u],v);
			break;
		}
		add(1,1,n,dfn[top[u]],dfn[u],v);
		u=fat[top[u]];
	}
	return re;
} 
int getlsum(int st,int ed) //一条链的和
{
	if(dfn[st]<dfn[ed]) swap(st,ed);
	int u=st,re=0;
	while(1)
	{
		if(dfn[top[u]]<=dfn[ed])
		{
			re+=get(1,1,n,dfn[ed],dfn[u])%mod;
			re%=mod;
			break;
		}
		re+=get(1,1,n,dfn[top[u]],dfn[u])%mod;
		re%=mod;
		u=fat[top[u]];
	}
	return re%mod;
} 

void getdis(int u, int fa) {
	for (int i = 0; i < g[u].size(); i++) {
		int v = g[u][i];
		if (v == fa) continue;
		getdis(v, u);
		dis[u] = max(dis[u], dis[v]);
	}
}
int father[500001][21];
void getfather(int u,int fa)
{
    father[u][0]=fa; //初始化
    for(int i=1;i<=20;i++)
    {
        father[u][i]=father[father[u][i-1]][i-1]; //转移 
    }
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(v==fa) continue;
        getfather(v,u); //向下搜索 
    }
}

//void getdeep(int u,int fa)
//{
//    dep[u]=dep[fa]+1; //统计深度 
//    for(int i=0;i<g[u].size();i++)
//    {
//        int v=g[u][i];
//        if(v==fa) continue;
//        getdeep(v,u);
//    }
//}

int getlca(int u,int v)
{
    if(dep[u]>dep[v]) swap(u,v); //保证v更深 
    int mul=dep[v]-dep[u],w=0;
    while(mul)
    {
        if(mul&1) v=father[v][w]; //向上跳 
        mul>>=1;
        w++;
    }
    if(u==v) return u;
    for(int i=20;i>=0;i--)
    {
        if(father[u][i]!=father[v][i]) //点不同,则不再一条链上 
        {
            u=father[u][i]; //向上跳 
            v=father[v][i];
        }
    }
    return father[u][0];
}
signed main()
{
	scanf("%lld%lld%lld%lld",&n,&q,&rt,&mod);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&w[i]);
	}
	for(int i=1,u,v;i<n;i++)
	{
		scanf("%lld%lld",&u,&v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	getdfsh(rt,0);
	gettd(rt,0);
	getdis(rt,0);
	getfather(rt,0);
	for(int i=1;i<=n;i++)
	{
		add(1,1,n,dfn[i],dfn[i],w[i]);
	}
	for(int i=1,opt,u,v,w;i<=q;i++)
	{
		scanf("%lld%lld",&opt,&u);
		if(opt==2)
		{
			scanf("%lld",&v);
			int lca=getlca(u,v);
			printf("%lld\n",((getlsum(u,lca)+getlsum(v,lca)-get(1,1,n,dfn[lca],dfn[lca]))%mod+mod)%mod);
		}
		if(opt==1)
		{
			scanf("%lld",&v);
			int lca=getlca(u,v);
			scanf("%lld",&w);
			w%=mod;
			addlsum(u,lca,w);
			addlsum(v,lca,w);
			add(1,1,n,dfn[lca],dfn[lca],-w);
		}
		if(opt==4)
		{
			//cout<<dfn[u]<<' '<<dis[u]<<endl;
			printf("%lld\n",get(1,1,n,dfn[u],dis[u])%mod);
		}
		if(opt==3)
		{
			scanf("%lld",&w);
			w%=mod;
			add(1,1,n,dfn[u],dis[u],w);
		}
	}
}

笛卡尔树

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[1000001],lson[1000001],rson[1000001],tr[1000001],st[1000001],len,pt,root;
void bd_t()
{
	pt=len;
	for(int i=1;i<=n;i++)
	{
		while(pt&&a[st[pt]]>a[i]) pt--; //维护单调栈
		if(pt) rson[st[pt]]=i; //如果有父亲,设到父亲的右儿子
		if(pt<len) lson[i]=st[pt+1]; //如果父亲有原右儿子,放到左儿子
		st[++pt]=i; //入栈
		len=pt;
	}
	root=st[1];
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	bd_t();
}

KMP

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char a[10000001],b[10000001];
int kmp[10000001],fail,strlena,strlenb,ans;
int main()
{
	scanf(" %s %s",a+1,b+1);
	strlena=strlen(a+1);
	strlenb=strlen(b+1);
	for(int i=2;i<=strlenb;i++)
	{
		while(fail>0 && b[i]!=b[fail+1]) fail=kmp[fail];
		if(b[i]==b[fail+1]) fail++;
		kmp[i]=fail; //找出失配指针 
	}
	fail=0; //初始化 
	for(int i=1;i<=strlena;i++)
	{
		while(fail>0 && a[i]!=b[fail+1]) fail=kmp[fail]; //跳fail指针 
		if(a[i]==b[fail+1]) fail++;
		if(fail==strlenb) //整串匹配 
		{
        ans++;
			fail=kmp[fail]; //向回跳 
		}
	}
   printf("%d",ans);
}

字符串哈希

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
string a,b;
unsigned long long dl=1,d=998244353,ha,hb;
long long la,lb,ans;
int main()
{
	cin>>a>>b;
	la=a.size();
	lb=b.size();
	for(int i=0;i<la;i++)
	{
		ha*=d;
		hb*=d;
		ha+=a[i];
		hb+=b[i];
		dl*=d;
	}
	if(ha==hb) ans++,las=la-1;
	for(int i=la;i<lb;i++)
	{
		hb*=d;
		hb=hb-b[i-la]*dl+b[i];
		if(ha==hb)
		{
			ans++;
		}
	}
	printf("%lld",ans);
}

AC自动机

#include<iostream>
#include<string>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int n,p,ans,jumper[1000001];
struct ac
{
	int nxt[27],fail,num,up;
}ac[1000001];
string s[151],t;
void add(string a,int kda)
{
	int P=0;
	for(int i=0;i<a.size();i++)
	{
		int t=a[i]-'a';
		if(!ac[P].nxt[t])
		{
			ac[P].nxt[t]=++p;
		}
		P=ac[P].nxt[t];
	}
	jumper[kda]=P;
	ac[P].num++;
	return;
}
void getfail()
{
	queue <int> q;
	for(int u=0;u<26;u++) //预处理根 
	{
		if(ac[0].nxt[u]) //有这条边 
		{
			ac[ac[0].nxt[u]].fail=0; //fail指针设到根
			q.push(ac[0].nxt[u]);
		}
	}
	while(!q.empty()) //bfs
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<26;i++)
		{
			if(ac[u].nxt[i]) //儿子存在 
			{
				ac[ac[u].nxt[i]].fail=ac[ac[u].fail].nxt[i]; //将儿子的fail指针指向自己fail指针的同一个儿子
				q.push(ac[u].nxt[i]); //压入队列 
			}
			else
			{
				ac[u].nxt[i]=ac[ac[u].fail].nxt[i];//跳到fail指针
			}
		}
	}
}

void work(string t)
{
	int AC=0,re=0,jump;
	for(int i=0;i<t.size();i++)
	{
		AC=ac[AC].nxt[t[i]-'a'];
		jump=AC;
		while(jump>0)
		{
			ac[jump].up++/*=ac[jump].num*/; //试试就逝世 
			jump=ac[jump].fail;
		}
	}
}
int serch(string a)
{
    int P=0;
    for(int i=0;i<a.size();i++)
    {
//    	cout<<P<<' ';
        int t=a[i]-'a';
        if(!ac[P].nxt[t])
        {
            return -1;
        }
        int jump=ac[P].nxt[t];
        while(jump>0&&ac[jump].num)
        {
            ans+=ac[jump].num;
            ac[jump].num=-1;
            jump=ac[jump].fail;
        }
        P=ac[P].nxt[t];
    }
//    cout<<P<<':'<<ac[P].up<<'\n';
    return ac[P].up;
}
int main()
{
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
  {
    cin>>s[i];
    add(s[i],i);
  }
  getfail();
  cin>>t;
  work(t);
}

manacher 算法

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
char b[50000001],a[50000001];
int len,ma,w,ans,mlc[50000001];
int main()
{
	cin>>a;
	b[0]='$';
	len=strlen(a);
	for(int i=0;i<len;i++)
	{
		b[i*2+1]='#';
		b[i*2+2]=a[i];
	}
	b[len*2+1]='#';
	b[len*2+2]='\0';
//	cout<<b;
	len=strlen(b);
	for(int i=1;i<len;i++)
	{
		if(i<ma)
		{
			mlc[i]=min(mlc[2*w-i],ma-i);
		}
		else
		{
			mlc[i]=1;
		}
		while(b[i+mlc[i]]==b[i-mlc[i]])
		{
			mlc[i]++;
		}
		if(mlc[i]+i>ma)
		{
			ma=mlc[i]+i;
			w=i;
		}
		ans=max(ans,mlc[i]-1);
	}
	printf("%d",ans);
}

欧拉筛

void ola()
{
	for(int i=2;i<=a;i++)
	{
		if(!vis[i]) prm[++len]=i;
		for(int z=1;z<=len&&i*prm[z]<=a;z++)
		{
			vis[i*prm[z]]=true;
			if(i%prm[z]==0) break;
		}
	}
}

埃氏筛

void work()
{
	for(long long i=2;i*i<=n;i++)
	{
		if(!vis[i])
		{
			for(long long z=i*i;z<=n;z+=i)
			{
				vis[z]=true;
			}
		}
	}
}
posted on 2023-05-04 18:28  lizhous  阅读(15)  评论(0编辑  收藏  举报