ACM竞赛板子


自己的板子积累,不断更新中

基本算法

贪心

区间覆盖问题

给出 m m m 个区间,选出最少的区间个数覆盖1~n.

struct node {
	int l,r;
	bool operator<(const node &t) const {
		return l<t.l;
	}
};
int main() {
	vector<node> ve;
	int n,m;
	cin>>n>>m;
	rep(i,1,m) {
		int l,r;
		cin>>l>>r;
		ve.pushk({l,r});
	}
	sort(ve.begin(),ve.end());
	int s=1;
	int ans=0;
	rep(idx,0,m-1) {
		int tmp=0;
		int j=idx;
		while(ve[j].l<=s && j<=m-1) tmp=max(tmp,ve[j++].r);
		//这里根据题目情况而定,有可能是s=tmp 
		s=tmp+1;
		ans++;
		idx=j-1;
		if(s>m) break;
	}
	cout<<ans<<endl;

	return 0;
}

快速幂加龟速乘

ll ksc(ll x,ll k)
{
	ll  res=0;
	while(k)
	{
		if(k&1) res=(res+x)%mod;
		k>>=1;
		x=(x+x)%mod; 
	 } 
	 return res;
}
ll qm(ll  x,ll k)
{
	ll res=1;
	while(k)
	{
		if(k&1)  res=ksc(res,x);
		k>>=1;
		x=ksc(x,x);
	 }  
	 return (ll)res;
}

ST表

int f[N][20];//f[i][j]表示i开始的2^j个数的最大值 
int n,q;
void init(){
	rep(i,1,n) f[i][0] = a[i];
	int t = __lg(n)+1;
	for(int j=1; j<t; ++j){
		for(int i=1; i<=n-(1<<j)+1; ++i){
			f[i][j] = max(f[i][j-1], f[i+(1<<(j-1))][j-1]);
		}
	}
}
int ask(int l,int r){
	int k = __lg(r-l+1);
	return max(f[l][k],f[r-(1<<k)+1][k]);
}

数学

区间互质

namespace qjhz {
    typedef long long ll;
    ll T, N, num;
    ll A, B;
    ll a[100];
    void prime(ll n) {
        num = 0;
        for (ll i = 2; i*i <= n; i++) {
            if ((n%i) == 0) {
                num++;
                a[num] = i;
                while ((n%i) == 0) {
                    n /= i;
                }
            }
        }
        if (n > 1) {
            num++;
            a[num] = n;
        }
        return;
    }
    ll solve(ll r, ll n) {
        prime(n);
        ll res = 0;
        for (ll i = 1; i < (1 << num); i++) {
            ll kk = 0;
            ll div = 1;
            for (ll j = 1; j <= num; j++) {
                if (i&(1 << (j - 1))) {
                    kk++;
                    div *= a[j];
                }
            }
            if (kk % 2)
                res += r / div;
            else
                res -= r / div;
        }
        return r - res;

    }

    ll que(ll L, ll R, ll k) {
        return solve(R, k) - solve(L - 1, k);
    }
}

三角形成型条件

a , b , c a,b,c a,b,c 满足, a b s ( b − c ) < a < b + c abs(b-c)<a<b+c abs(bc)<a<b+c , 则 a , b , c a,b,c a,b,c 可以构成三角形。

合法括号序列

长度为 2 n 2n 2n 且包含 k k k 种不同类型的括号的合法括号序列数量为:

f n = 1 n + 1 ∗ C 2 n n ∗ k n f_n = \frac{1}{n+1}*C_{2n}^n*k^n fn=n+11C2nnkn

指数取模

出处:
https://blog.csdn.net/doyouseeman/article/details/51863382
在这里插入图片描述

欧拉函数

参考:https://www.acwing.com/solution/content/3952/
在这里插入图片描述

void solve(int n){
    phi[1]=1;
    for (int i = 2; i <=n; ++i ){
        if(!st[i]) p[tot++]=i,phi[i]=i-1;
        for(int j=0; p[j]<=n/i; ++j){
            st[p[j]*i] = true;
            if(i%p[j]==0) {
                phi[i*p[j]] = phi[i]*p[j];
                break;
            }
            phi[i*p[j]] = phi[i]*(p[j]-1);
        }
    }
}

exgcd求逆元

void exgcd(int a, int b, int &x, int &y){
	if(!b) x = 1, y = 0;
	else{
		exgcd(b, a % b, y, x);
		y -= a / b * x;
	}
}
int main(){
	int a, b, x, y;
	scanf("%d%d", &a, &b);
	exgcd(a, b, x, y);
	printf("%d", (x % b + b) % b);
	return 0;
} 

递推法求逆元

inv[i]=(mod-mod/i)*inv[mod%i]%mod (其中mod为模数,要求为奇质数

递推法预处理阶乘逆元

void init(){
    f[0]=inf[0]=inf[1]=f[1]=1;
    rep(i,2,N-2){
        f[i]=1ll*f[i-1]*i%mod;
        inf[i]=1ll*(mod-mod/i)*inf[mod%i]%mod;
    }
    rep(i,2,N-2){
        inf[i]=inf[i-1]*inf[i]%mod;
    }
}

卢卡斯定理

int qmi(int x,int k){
	int res=1;
	while(k){
		if(k&1) res=1ll*res*x%mod;
		k>>=1;
		x=1ll*x*x%mod; 
	}
	return res;
}
int C(int n,int m){
	if(m>n) return 0;
	return 1ll*f[n]*qmi(f[m],mod-2)%mod*qmi(f[n-m],mod-2)%mod;
}
int lucas(ll n,ll m){
	if(!m) return 1; 
	return 1ll*C(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
void init(){
	f[0]=1;
	rep(i,1,mod){
		f[i]=1ll*f[i-1]*i%mod;	
	}
}

判断质数

质数分布的规律:大于等于5的质数一定和6的倍数相邻
参考大佬:https://blog.csdn.net/songyunli1111/article/details/78690447


int isPrime(int n)
{	//返回1表示判断为质数,0为非质数,在此没有进行输入异常检测
	float n_sqrt;
	if(n==2 || n==3) return 1;
	if(n%6!=1 && n%6!=5) return 0;
	n_sqrt=floor(sqrt((float)n));
	for(int i=5;i<=n_sqrt;i+=6)
	{
	    if(n%(i)==0 | n%(i+2)==0) return 0;
	}
        return 1;
} 

欧拉筛(线性筛)

时间复杂度O(n)

void  prime(int n)
{
	for(int i=2; i<=n; i++)
	{
		if(!st[i]) p[ans++]=i;
		for(int j=0; p[j]<=n/i; j++)
		{
			st[p[j]*i]=1;
			if(i%p[j]==0) break;
		}
	}
}

阶乘和阶乘逆元,组合数(递推)

int qmi(int x,int k)
{
	int res=1;
	while(k)
	{
		if(k&1) res=1ll*res*x%mod;
		k>>=1;
		x=1ll*x*x%mod;
	}
	return res;
}
void init()
{
   	f[0]=inf[0]=1;
	for(int i=1; i<N; i++)
	{
		f[i]=1ll*f[i-1]*i%mod;
		inf[i]=1ll*inf[i-1]*qmi(i,mod-2)%mod;
	}  		
}

计算几何

点到线段的最短距离

参考:https://blog.csdn.net/Mr_HCW/article/details/82816490

typedef struct node
{
	double x, y;
}Point;
double getDis2(Point a, Point b)  //得到两点距离的平方
{
	return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
}
 
double disMin(Point A, Point B,Point P)
{
	double r = ((P.x - A.x)*(B.x - A.x) + (P.y - A.y)*(B.y - A.y)) / getDis2(A,B);
	if (r <= 0) return sqrt(getDis2(A,P));  //第一种情况, 返回AP的长
	else if (r >= 1) return sqrt(getDis2(B,P)); //第二种情况, 返回BP的长度
	else                           //第三种情况, 返回PC的长度
	{
		double AC = r*sqrt(getDis2(A,B));  //先求AC的长度,(AC=r*|AB|)
		return sqrt(getDis2(A,P)-AC*AC); //再勾股定理返回PC的长度
	}

二维几何

kuangbin计算几何板子

const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//`Compares a double to zero`
int sgn(double x){
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
//square of a double
inline double sqr(double x){return x*x; }
struct Point{
    double x,y;
    Point(){}
    Point(double _x,double _y){
        x = _x;
        y = _y;
    }
    void input(){
        scanf("%lf%lf",&x,&y);
    }
    void output(){
        printf("%.2f %.2f\n",x,y);
    }
    bool operator == (Point b)const{
        return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
    }
    bool operator < (Point b)const{
        return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
    }
    Point operator -(const Point &b)const{
        return Point(x-b.x,y-b.y);
    }
    //叉积
    double operator ^(const Point &b)const{
        return x*b.y - y*b.x;
    }
    //点积
    double operator *(const Point &b)const{
        return x*b.x + y*b.y;
    }
    //返回长度
    double len(){
        return hypot(x,y);//库函数
    }
    //返回长度的平方
    double len2(){
        return x*x + y*y;
    }
    //返回两点的距离
    double distance(Point p){
        return hypot(x-p.x,y-p.y);
    }
    Point operator +(const Point &b)const{
        return Point(x+b.x,y+b.y);
    }
    Point operator *(const double &k)const{
        return Point(x*k,y*k);
    }
    Point operator /(const double &k)const{
        return Point(x/k,y/k);
    }
    //`计算pa  和  pb 的夹角`
    //`就是求这个点看a,b 所成的夹角`
    //`测试 LightOJ1203`
    double rad(Point a,Point b){
        Point p = *this;
        return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
    }
    //`化为长度为r的向量`
    Point trunc(double r){
        double l = len();
        if(!sgn(l))return *this;
        r /= l;
        return Point(x*r,y*r);
    }
    //`逆时针旋转90度`
    Point rotleft(){
        return Point(-y,x);
    }
    //`顺时针旋转90度`
    Point rotright(){
        return Point(y,-x);
    }
    //`绕着p点逆时针旋转angle`
    Point rotate(Point p,double angle){
        Point v = (*this) - p;
        double c = cos(angle), s = sin(angle);
        return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
    }
};



struct Line{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e){
        s = _s;
        e = _e;
    }
    bool operator ==(Line v){
        return (s == v.s)&&(e == v.e);
    }
    //`根据一个点和倾斜角angle确定直线,0<=angle<pi`
    Line(Point p,double angle){
        s = p;
        if(sgn(angle-pi/2) == 0){
            e = (s + Point(0,1));
        }
        else{
            e = (s + Point(1,tan(angle)));
        }
    }
    //ax+by+c=0
    Line(double a,double b,double c){
        if(sgn(a) == 0){
            s = Point(0,-c/b);
            e = Point(1,-c/b);
        }
        else if(sgn(b) == 0){
            s = Point(-c/a,0);
            e = Point(-c/a,1);
        }
        else{
            s = Point(0,-c/b);
            e = Point(1,(-c-a)/b);
        }
    }
    void input(){
        s.input();
        e.input();
    }
    void adjust(){
        if(e < s)swap(s,e);
    }
    //求线段长度
    double length(){
        return s.distance(e);
    }
    //`返回直线倾斜角 0<=angle<pi`
    double angle(){
        double k = atan2(e.y-s.y,e.x-s.x);
        if(sgn(k) < 0)k += pi;
        if(sgn(k-pi) == 0)k -= pi;
        return k;
    }
    //`点和直线关系`
    //`1  在左侧`
    //`2  在右侧`
    //`3  在直线上`
    int relation(Point p){
        int c = sgn((p-s)^(e-s));
        if(c < 0)return 1;
        else if(c > 0)return 2;
        else return 3;
    }
    // 点在线段上的判断
    bool pointonseg(Point p){
        return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0;
    }
    //`两向量平行(对应直线平行或重合)`
    bool parallel(Line v){
        return sgn((e-s)^(v.e-v.s)) == 0;
    }
    //`两线段相交判断`
    //`2 规范相交`
    //`1 非规范相交`
    //`0 不相交`
    int segcrossseg(Line v){
        int d1 = sgn((e-s)^(v.s-s));
        int d2 = sgn((e-s)^(v.e-s));
        int d3 = sgn((v.e-v.s)^(s-v.s));
        int d4 = sgn((v.e-v.s)^(e-v.s));
        if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;
        return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
            (d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
            (d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
            (d4==0 && sgn((e-v.s)*(e-v.e))<=0);
    }
    //`直线和线段相交判断`
    //`-*this line   -v seg`
    //`2 规范相交`
    //`1 非规范相交`
    //`0 不相交`
    int linecrossseg(Line v){
        int d1 = sgn((e-s)^(v.s-s));
        int d2 = sgn((e-s)^(v.e-s));
        if((d1^d2)==-2) return 2;
        return (d1==0||d2==0);
    }
    //`两直线关系`
    //`0 平行`
    //`1 重合`
    //`2 相交`
    int linecrossline(Line v){
        if((*this).parallel(v))
            return v.relation(s)==3;
        return 2;
    }
    //`求两直线的交点`
    //`要保证两直线不平行或重合`
    Point crosspoint(Line v){
        double a1 = (v.e-v.s)^(s-v.s);
        double a2 = (v.e-v.s)^(e-v.s);
        return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
    }
    //点到直线的距离
    double dispointtoline(Point p){
        return fabs((p-s)^(e-s))/length();
    }
    //点到线段的距离
    double dispointtoseg(Point p){
        if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)
            return min(p.distance(s),p.distance(e));
        return dispointtoline(p);
    }
    //`返回线段到线段的距离`
    //`前提是两线段不相交,相交距离就是0了`
    double dissegtoseg(Line v){
        return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));
    }
    //`返回点p在直线上的投影`
    Point lineprog(Point p){
        return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
    }
    //`返回点p关于直线的对称点`
    Point symmetrypoint(Point p){
        Point q = lineprog(p);
        return Point(2*q.x-p.x,2*q.y-p.y);
    }
};

平面最近点对

n l o g ( n ) nlog(n) nlog(n)

const int MAXN = 100010;
const double eps = 1e-8;
const double INF = 1e20;
struct Point{
    double x,y;
    void input(){
        scanf("%lf%lf",&x,&y);
    }
};
double dist(Point a,Point b){
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
Point p[MAXN];
Point tmpt[MAXN];
bool cmpx(Point a,Point b){
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}
bool cmpy(Point a,Point b){
    return a.y < b.y || (a.y == b.y && a.x < b.x);
}
double Closest_Pair(int left,int right){
    double d = INF;
    if(left == right)return d;
    if(left+1 == right)return dist(p[left],p[right]);
    int mid = (left+right)/2;
    double d1 = Closest_Pair(left,mid);
    double d2 = Closest_Pair(mid+1,right);
    d = min(d1,d2);
    int cnt = 0;
    for(int i = left;i <= right;i++){
        if(fabs(p[mid].x - p[i].x) <= d)
            tmpt[cnt++] = p[i];
    }
    sort(tmpt,tmpt+cnt,cmpy);
    for(int i = 0;i < cnt;i++){
        for(int j = i+1;j < cnt && tmpt[j].y - tmpt[i].y < d;j++)
            d = min(d,dist(tmpt[i],tmpt[j]));
    }
    return d;
}
int main(){
    int n;
    while(scanf("%d",&n) == 1 && n){
        for(int i = 0;i < n;i++)p[i].input();
        sort(p,p+n,cmpx);
        printf("%.2lf\n",Closest_Pair(0,n-1));
    }
    return 0;
}

高斯消元求行列式的值

参考:https://blog.csdn.net/xyz32768/article/details/81413569
数组a存储的是矩阵

ll det() {
    int i, j, k;
	ll res = 1;
    for(i=1; i<=n; ++i){
        ll qaq = qpow(a[i][i], mod- 2);
        for( j=i + 1; j<=n; ++j) {
            ll tmp = 1ll * a[j][i] * qaq % mod;
            for(k=1; k<=n; ++k) a[j][k] = (a[j][k] - 1ll * a[i][k] *
                tmp % mod + mod) % mod;
        }
    }
    for(i=1; i<=n; ++i) res = 1ll * res * a[i][i] % mod;
    return (res+mod)%mod;
}

数据结构和图论

迪杰斯特拉

struct ShortPath{
	int head[N],to[M],len[M],nxt[M],tot;
	int dis[N],vis[N];
	
	void init() {
		tot=0;
		memset(head,0,sizeof(head));
	}
	
	void add(int u,int v,int w) {
		to[++tot]=v;len[tot]=w;nxt[tot]=head[u];head[u]=tot;
	}
	
	void dijkstra() {
		memset(dis,0x3f,sizeof(dis));
		memset(vis,0,sizeof(vis));
		priority_queue<PII> pq;
		dis[s]=0;
		pq.push(make_pair(0,s));
		while(!pq.empty()) {
			int u=pq.top().second;
			pq.pop();
			if(vis[u]) continue;
			vis[u]=1;
			for(int i=head[u];i;i=nxt[i])
				if(dis[to[i]]>dis[u]+len[i]) {
					dis[to[i]]=dis[u]+len[i];
					pq.push(make_pair(-dis[to[i]],to[i]));
				}
		}
	}
}sp,sn;

滑动窗口

	int n,k;
	cin>>n>>k;
	rep(i,1,n) cin>>a[i];
	rep(i,1,n) {
		//约束区间长度
		while(hh<=tt && q[hh]<=i-k) ++hh;
		//约束单调性
		while(hh<=tt && a[q[tt]]>=a[i]) --tt;
		q[++tt]=i;
		if(i>=k) printf("%d ",a[q[hh]]);
	}
	hh=1,tt=0;
	puts("");
	rep(i,1,n) {
		//约束区间长度
		while(hh<=tt && q[hh]<=i-k) ++hh;
		//约束单调性
		while(hh<=tt && a[q[tt]]<=a[i]) --tt;
		q[++tt]=i;
		if(i>=k) printf("%d ",a[q[hh]]);
	}

树上倍增求LCA

int pa[N][20];//pa[i][j]:i的2^i级祖先 
int dep[N],lg[N];
int h[N],e[N*2],ne[N*2],idx;
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a], h[a]=idx++;
}
void dfs(int u,int fa){
	dep[u] = dep[fa] + 1;
	pa[u][0] = fa;
	//核心转移数组,u的2^i级祖先等于u的2^(i-1)级祖先的2^(i-1)级祖先
	//2^i = 2^(i-1) + 2^(i-1) 
	//这里只能从小到大更新,因为pa[u][i]依赖pa[u][i-1]的值 
	for(int i=1; i<=lg[dep[u]]-1; ++i){
		pa[u][i] = pa[pa[u][i-1]][i-1];
	}
	for(int i=h[u]; ~i; i=ne[i]){
		int it = e[i];
		if(it==fa) continue;
		dfs(it,u);
	}
}
int lca(int x,int y){
	//设定dep[x]>dep[y],方便处理 
	if(dep[x]<dep[y]) swap(x,y);
	//先跳到统一深度 
	//这里lg[]-1,是因为lg[i]的含义是:log2(i)+1 ,这个可以自己修改 
	while(dep[x]>dep[y]) x = pa[x][lg[dep[x] - dep[y]]-1];
	if(x==y) return x;//x是y的祖先的情况 
	for(int i=lg[dep[x]]-1; i>=0; i--){
		//我们要跳到他们Lca的下一层,不能直接跳到Lca因为可以能会误判
		//因为他们的lca的祖先也满足 pa[x][i]==pa[y][i]
		if(pa[x][i]!=pa[y][i]) x=pa[x][i],y=pa[y][i];
	} 
	return pa[x][0];
}
int main() {
	mem(h, -1);
	rep(i,1,N-9) lg[i] = lg[i-1] + ((1<<lg[i-1])==i);
	int n,m,s;
	cin>>n>>m>>s;
	rep(i,1,n-1){
		int u,v;
		scanf("%d %d",&u, &v);
		add(u,v),add(v,u);
	}
	//dfs预处理出pa数组 
	dfs(s,0);
	while(m--){
		int u,v;
		scanf("%d %d",&u,&v);
		printf("%d\n",lca(u,v));
	} 
	return 0;
}

主席树

区间第k小

struct node{
	int ls,rs;//左右子树编号
	int cnt; 
}tr[N*4+17*N]; 
int rt[N],n,m,a[N],idx;//存储版本i的根节点的编号
vector<int> ve;
int get(int x){
	return lower_bound(ve.begin(), ve.end(),x)-ve.begin()+1;
} 
//建树 ,此时的cnt为0 
int build(int l,int r){
	int q = ++idx;
	if(l>=r) return q;
	int mid = l+r>>1;
	tr[q].ls = build(l,mid),tr[q].rs=build(mid+1,r);
	return q;
}
int insert(int p,int l,int r,int x){
	int q = ++idx;
	tr[q]=tr[p];
	if(l>=r) {
		tr[q].cnt++;
		return q;
	}
	int mid = l+r>>1;
	if(x<=mid) tr[q].ls=insert(tr[p].ls,l,mid,x);
	else tr[q].rs = insert(tr[p].rs,mid+1,r,x);
	tr[q].cnt = tr[tr[q].ls].cnt + tr[tr[q].rs].cnt;
	return q; 
} 
int ask(int q,int p,int l,int r,int k){
	if(l>=r) return l;
	int cnt = tr[tr[q].ls].cnt - tr[tr[p].ls].cnt;
	int mid = l+r>>1;
	if(k<=cnt) return ask(tr[q].ls,tr[p].ls,l,mid,k);
	else return ask(tr[q].rs,tr[p].rs,mid+1,r,k-cnt);
}
int main() {

	cin>>n>>m;
	rep(i,1,n) scanf("%d",a+i),ve.emk(a[i]);
	sort(ve.begin(),ve.end());
	ve.erase(unique(ve.begin(), ve.end()),ve.end());
	rt[0]=build(1,ve.size());
	rep(i,1,n) rt[i]=insert(rt[i-1],1,ve.size(),get(a[i]));
	while(m--){
		int l,r,k;
		scanf("%d %d %d",&l,&r,&k);
		printf("%d\n",ve[ask(rt[r],rt[l-1],1,ve.size(),k)-1]);
	}
	return 0;
}

线段树

#define ll long long
#define lp p<<1
#define rp p<<1|1
struct SegT {
	int l,r;
	ll sum;
	ll add;
} tr[N*4];
void build(int p,int l,int r) {
	tr[p].l=l,tr[p].r=r;
	if(l>=r) {
		tr[p].sum=a[l],tr[p].add=0;
		return ;
	}
	int mid = (l+r)>>1;
	build(lp,l,mid);
	build(rp,mid+1,r);
	tr[p].sum = tr[lp].sum + tr[rp].sum;
}
void spread(int p) {
	if(tr[p].add) {
		tr[lp].sum+=1ll*(tr[lp].r-tr[lp].l+1)*tr[p].add;
		tr[rp].sum+=1ll*(tr[rp].r - tr[rp].l +1 )*tr[p].add;
		tr[lp].add+=tr[p].add;
		tr[rp].add+=tr[p].add;
		tr[p].add=0;
	}
}
void change(int p,int l,int r,ll k) {
	if(tr[p].l>=l && tr[p].r <= r) {
		tr[p].sum+=1ll*(tr[p].r-tr[p].l+1)*k;
		tr[p].add+=k;
		return ;
	}
	spread(p);
	int mid = (tr[p].l + tr[p].r)>>1;
	if(l<=mid) change(lp,l,r,k);
	if(r>mid) change(rp,l,r,k);
	tr[p].sum = tr[lp].sum + tr[rp].sum;
}
ll ask(int p,int l,int r) {
	if(tr[p].l>=l && tr[p].r <= r) {
		return tr[p].sum;
	}
	spread(p);
	int mid = (tr[p].l + tr[p].r)>>1;
	ll res=0;
	if(l<=mid) res+=ask(lp,l,r);
	if(r>mid)  res+=ask(rp,l,r);
	tr[p].sum = tr[lp].sum + tr[rp].sum;
	return res;
}

带权并查集

参考:https://blog.csdn.net/yjr3426619/article/details/82315133
hdu3038:https://acm.hdu.edu.cn/showproblem.php?pid=3038

int find(int x){
	if(x!=p[x]) {
		int t=p[x];
		p[x]=find(p[x]);
		val[x]+=val[t];
	}
	return p[x];
}
void merge(int a,int b,int c){
	int fa=find(a),fb=find(b);
	if(fa!=fb){
		p[fa]=fb;
		val[fa]=val[b]-val[a]+1ll*c;
	}
}
int main(){
	int n,m;
	while(~scanf("%d %d",&n,&m)){
	for(int i=0; i<=n; ++i) p[i]=i,val[i]=0;
	int ans=0;
	for(int i=0; i<m; ++i){
		int a,b;
		ll c;
		scanf("%d %d %lld",&a,&b,&c);
		a--;
		int fa=find(a),fb=find(b);
		if(fa!=fb){
			merge(a,b,c);
		}
		else{
			if(val[a]-val[b]!=c) ans++;
		}
	}
	printf("%d\n",ans);
	}
	
	return 0;
} 

dfs序

void Dfs(int u, int fa, int dep)
{
    seq[++cnt] = u;
    st[u] = cnt;
    int len = edge[u].size();
    for(int i = 0; i < len; i++) {
        int v = edge[u][i];
        if(v != fa) {
            Dfs(v, u, dep+1);
        }
    }
    seq[++cnt] = u;
    ed[u] = cnt;
}

小根堆的建立

边输入边建立,相当于在在堆中插入一个新的元素,每次直接放到末尾,然后进行堆化。
找到第一个非叶节点进行堆化, n / 2 n/2 n/2

//堆化 
void build(int n){
	int t=n;
	while(t/2>=1 && a[t/2]>a[t]){
		swap(a[t/2],a[t]);
		t/=2;
	}
}
int main(){
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1; i<=n; i++){
		scanf("%d",a+i);
		build(i);
	}

}

字典树

const int N =1e5+9;
const int M = 30*N;
int son[M][2],idx;
int a[N];
void insert(int x){
	int p=0;
	rep(i,0,30){
		int t=x>>i&1;
		if(!son[p][t]) son[p][t]=++idx;
		p=son[p][t];
	}
}
int ask(int x){
	int p=0;
	int res=0;
	rep(i,0,30){
		int t=x>>i&1;
		if(son[p][!t]){
			p=son[p][!t];
			res+=1<<i;
		}
		else p=son[p][t];
	}
	return res;
}
int main(){
	int n;
	cin>>n;
	rep(i,0,n-1) scanf("%d",a+i),insert(a[i]);
	int res=0;
	rep(i,0,n-1){
		res=max(res,ask(a[i]));
	}
	cout<<res<<'\n';
	return 0;
} 

动态规划

环形石子合并

把环形链扩展成2倍数组

	int n;
	cin>>n;
	rep(i,1,n) cin>>a[i],sum[i]=sum[i-1]+a[i];
	rep(i,n+1,2*n-1) a[i]=a[i-n],sum[i]=sum[i-1]+a[i];
	//puts("");
	rep(len,2,n){
		rep(j,1,2*n-1){
			int l=j,r=j+len-1;
			if(r>2*n-1) break;
			f[l][r]=INF;
			rep(k,l,r) f[l][r]=min(f[l][r], f[l][k]+f[k+1][r]+sum[r]-sum[l-1]);
		}
	}	
	int ans=INF;
	rep(i,1,n) {
		//cout<<i<<" "<<i+n-1<<' '<<f[i][i+n-1]<<'\n';
		ans=min(ans,f[i][i+n-1]);
	}
	cout<<ans<<'\n';

最长公共子序列滚动数组写法

	int p=0;
	rep(i,1,n){
		p=1-p;
		rep(j,1,n){
			if(a[i]==b[j]) f[p][j]=f[1-p][j-1]+1;
			else f[p][j]=max(f[1-p][j],f[p][j-1]);
		}
	}
	cout<<f[p][n]<<'\n';

数位dp

此模板来源于洛谷大佬:
https://www.luogu.com.cn/blog/virus2017/shuweidp

ll dfs(int pos,int pre,int st,……,int lead,int limit)//记搜
{
    if(pos>len) return st;//剪枝
    if((dp[pos][pre][st]……[……]!=-1&&(!limit)&&(!lead))) return dp[pos][pre][st]……[……];//记录当前值
    ll ret=0;//暂时记录当前方案数
    int res=limit?a[len-pos+1]:9;//res当前位能取到的最大值
    for(int i=0;i<=res;i++)
    {
        //有前导0并且当前位也是前导0
        if((!i)&&lead) ret+=dfs(……,……,……,i==res&&limit);
        //有前导0但当前位不是前导0,当前位就是最高位
        else if(i&&lead) ret+=dfs(……,……,……,i==res&&limit); 
        else if(根据题意而定的判断) ret+=dfs(……,……,……,i==res&&limit);
    }
    if(!limit&&!lead) dp[pos][pre][st]……[……]=ret;//当前状态方案数记录
    return ret;
}
ll part(ll x)//把数按位拆分
{
    len=0;
    while(x) a[++len]=x%10,x/=10;
    memset(dp,-1,sizeof dp);//初始化-1(因为有可能某些情况下的方案数是0)
    return dfs(……,……,……,……);//进入记搜
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&l,&r);
        if(l) printf("%lld",part(r)-part(l-1));//[l,r](l!=0)
        else printf("%lld",part(r)-part(l));//从0开始要特判
    }
    return 0;
}

完全背包

每种物品能用无限多次

int a[N],b[N];
int f[N];
int main() {

	int n,m;
	cin>>n>>m;
	rep(i,1,n){
		cin>>a[i]>>b[i];
	}
	rep(i,1,n){
		rep(j,a[i],m){
			f[j]=max(f[j],f[j-a[i]]+b[i]);
		}
	}
	cout<<f[m]<<'\n';
	return 0;
}

多重背包二进制优化

每种物品最多用 x i x_i xi

int v[N],w[N],tot;
int f[N];
int main() {
	int n,m;
	cin>>n>>m;
	rep(i,1,n){
		int x,y,z;
		cin>>x>>y>>z;
		int t=1;
		while(z>=t){
			v[++tot]=t*x,w[tot]=t*y;
			z-=t;
			t<<=1;
		}
		if(z) 	v[++tot]=z*x,w[tot]=z*y;
	}
	n=tot;
	rep(i,1,n){
		per(j,m,v[i]){
			f[j]=max(f[j],f[j-v[i]]+w[i]);
		}
	}
	cout<<f[m]<<'\n';

多重背包单调队列优化

int f[N],g[N],q[N]; 
int main() {
	int n,m;
	cin>>n>>m;
	for(int i=1; i<=n; ++i){
		memcpy(g,f,sizeof f);
		int v,w,s;
		cin>>v>>w>>s;
		for(int j=0; j<v; ++j){
			//我们按照余数分类,对于每个j,我们用单调队列维护 
			//f[j]=max(f[j-v]+w,f[j-2v]+2w,...f[j-sv]+sw);
			int hh=1,tt=0;
			for(int k=j; k<=m; k+=v){
				if(hh<=tt && q[hh]<k-s*v) ++hh;
				if(hh<=tt) f[k]=max(g[k],g[q[hh]]+(k-q[hh])/v*w);
				while(hh<=tt && g[q[tt]]+(k-q[tt])/v*w<=g[k]) --tt;
				q[++tt]=k;
			}
		}
	}
	cout<<f[m]<<'\n';

分祖背包

int f[N];
int v[N][N],w[N][N];
int main() {
	int n,m;
	cin>>n>>m;
	rep(i,1,n){
		int x,y,z;
		cin>>x>>y>>z;
		v[x][++v[x][0]]=y;
		w[x][++w[x][0]]=z;
	}
	rep(i,1,n){
		per(j,m,1){
			rep(k,1,v[i][0]){
				if(j>=v[i][k])
				f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
			}
		}
	}
	cout<<f[m]<<'\n';
  • 6
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 字符串处理 5 1.1 KMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2 e-KMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.3 Manacher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.4 AC 自动机 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.5 后缀数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5.1 DA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5.2 DC3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.6 后缀自动机 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.6.1 基本函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.6.2 例题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.7 字符串 hash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2 数学 25 2.1 素数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.1.1 素数筛选(判断 <MAXN 的数是否素数) . . . . . . . . . . . . . . . . 25 2.1.2 素数筛选(筛选出小于等于 MAXN 的素数) . . . . . . . . . . . . . . . 25 2.1.3 大区间素数筛选(POJ 2689) . . . . . . . . . . . . . . . . . . . . . . . 25 2.2 素数筛选和合数分解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.3 扩展欧几里得算法(求 ax+by=gcd 的解以及逆元) . . . . . . . . . . . . . . . 27 2.4 求逆元 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.4.1 扩展欧几里德法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.4.2 简洁写法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.4.3 利用欧拉函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.5 模线性方程组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.6 随机素数测试和大数分解 (POJ 1811) . . . . . . . . . . . . . . . . . . . . . . . 29 2.7 欧拉函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.7.1 分解质因素求欧拉函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.7.2 筛法欧拉函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.7.3 求单个数的欧拉函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.7.4 线性筛(同时得到欧拉函数和素数表) . . . . . . . . . . . . . . . . . . 32 2.8 高斯消元(浮点数) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 2.9 FFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 2.10 高斯消元法求方程组的解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.10.1 一类开关问题,对 2 取模的 01 方程组 . . . . . . . . . . . . . . . . . . . 37 2.10.2 解同余方程组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 2.11 整数拆分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 2.12 求 A B 的约数之和对 MOD 取模 . . . . . . . . . . . . . . . . . . . . . . . . . . 43 2.13 莫比乌斯反演 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.13.1 莫比乌斯函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.13.2 例题:BZOJ2301 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.14 Baby-Step Giant-Step . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 2.15 自适应 simpson 积分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 2.16 斐波那契数列取模循环节 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 2.17 原根 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 2.18 快速数论变换 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.18.1 HDU4656 卷积取模 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.19 其它公式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 2.19.1 Polya . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 kuangbin 1 ACM Template of kuangbin 3 数据结构 56 3.1 划分树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 3.2 RMQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.2.1 一维 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.2.2 二维 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.3 树链剖分 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 3.3.1 点权 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 3.3.2 边权 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 3.4 伸展树(splay tree) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 3.4.1 例题:HDU1890 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 3.4.2 例题:HDU3726 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 3.5 动态树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 3.5.1 SPOJQTREE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 3.5.2 SPOJQTREE2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 3.5.3 SPOJQTREE4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 3.5.4 SPOJQTREE5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 3.5.5 SPOJQTREE6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 3.5.6 SPOJQTREE7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 3.5.7 HDU4010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 3.6 主席树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 3.6.1 查询区间多少个不同的数 . . . . . . . . . . . . . . . . . . . . . . . . . . 95 3.6.2 静态区间第 k 大 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 3.6.3 树上路径点权第 k 大 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 3.6.4 动态第 k 大 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 3.7 Treap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 3.8 KD 树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 3.8.1 HDU4347 K 近邻 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 3.8.2 CF44G . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 3.8.3 HDU4742 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 3.9 替罪羊树 (ScapeGoat Tree) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 3.9.1 CF455D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 3.10 动态 KD 树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 3.11 树套树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 3.11.1 替罪羊树套 splay . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 4 图论 130 4.1 最短路 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 4.1.1 Dijkstra 单源最短路 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 4.1.2 Dijkstra 算法 + 堆优化 . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 4.1.3 单源最短路 bellman_ford 算法 . . . . . . . . . . . . . . . . . . . . . . . 131 4.1.4 单源最短路 SPFA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 4.2 最小生成树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 4.2.1 Prim 算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 4.2.2 Kruskal 算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 4.3 次小生成树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 4.4 有向图的强连通分量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 4.4.1 Tarjan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 4.4.2 Kosaraju . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 4.5 图的割点、桥和双连通分支的基本概念 . . . . . . . . . . . . . . . . . . . . . . . 138 4.6 割点与桥 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 4.6.1 模板 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 kuangbin 2 ACM Template of kuangbin 4.6.2 调用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 4.7 边双连通分支 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 4.8 点双连通分支 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 4.9 最小树形图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 4.10 二分图匹配 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 4.10.1 邻接矩阵(匈牙利算法) . . . . . . . . . . . . . . . . . . . . . . . . . . 149 4.10.2 邻接表(匈牙利算法) . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 4.10.3 Hopcroft-Karp 算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 4.11 二分图多重匹配 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 4.12 二分图最大权匹配(KM 算法) . . . . . . . . . . . . . . . . . . . . . . . . . . 153 4.13 一般图匹配带花树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 4.14 一般图最大加权匹配 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 4.15 生成树计数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 4.16 最大流 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 4.16.1 SAP 邻接矩阵形式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 4.16.2 SAP 邻接矩阵形式 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 4.16.3 ISAP 邻接表形式 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 4.16.4 ISAP+bfs 初始化 + 栈优化 . . . . . . . . . . . . . . . . . . . . . . . . . 165 4.16.5 dinic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 4.16.6 最大流判断多解 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 4.17 最小费用最大流 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 4.17.1 SPFA 版费用流 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 4.17.2 zkw 费用流 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 4.18 2-SAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 4.18.1 染色法(可以得到字典序最小的解) . . . . . . . . . . . . . . . . . . . . 172 4.18.2 强连通缩点法(拓扑排序只能得到任意解) . . . . . . . . . . . . . . . . 173 4.19 曼哈顿最小生成树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 4.20 LCA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 4.20.1 dfs+ST 在线算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 4.20.2 离线 Tarjan 算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 4.20.3 LCA 倍增法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 4.21 欧拉路 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 4.21.1 有向图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 4.21.2 无向图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 4.21.3 混合图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 4.22 树分治 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 4.22.1 点分治 -HDU5016 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 4.22.2 * 点分治 -HDU4918 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 4.22.3 链分治 -HDU5039 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 5 搜索 205 5.1 Dancing Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 5.1.1 精确覆盖 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 5.1.2 可重复覆盖 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 5.2 八数码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 5.2.1 HDU1043 反向搜索 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 6 动态规划 212 6.1 最长上升子序列 O(nlogn) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 6.2 背包 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 6.3 插头 DP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 kuangbin 3 ACM Template of kuangbin 6.3.1 HDU 4285 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 7 计算几何 218 7.1 二维几何 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 7.2 三维几何 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 7.3 平面最近点对 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242 7.4 三维凸包 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 7.4.1 HDU4273 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 8 其他 249 8.1 高精度 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 8.2 完全高精度 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 8.3 strtok 和 sscanf 结合输入 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 8.4 解决爆栈,手动加栈 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 8.5 STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 8.5.1 优先队列 priority_queue . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 8.5.2 set 和 multiset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 8.6 输入输出外挂 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 8.7 莫队算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 8.7.1 分块 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 8.7.2 Manhattan MST 的 dfs 顺序求解 . . . . . . . . . . . . . . . . . . . . . . 260 8.8 VIM 配置 .

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值