==模板==

快读:

ll rd()
{
    ll a=0;int f=0;char p=getchar();
    while(!isdigit(p)){f|=p=='-';p=getchar();}
    while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=getchar();}
    return f?-a:a;
}

组合数:

ll euclid(ll a, ll b, ll &x, ll &y) {
	if (!b) return x = 1, y = 0, a;
	ll d = euclid(b, a % b, y, x);
	return y -= a/b * x, d;
}
struct mint {
	ll x;
	mint() :x(0){}
	mint(ll xx) : x(xx) {}
	operator ll(){return x;}
	mint operator+(mint b) { return mint((x + b.x) % P); }
	mint operator-(mint b) { return mint((x - b.x + P) % P); }
	mint operator*(mint b) { return mint((x * b.x) % P); }
	mint operator/(mint b) { return *this * invert(b); }
	mint invert(mint a) {
		ll x, y, g = euclid(a.x, P, x, y);
		assert(g == 1); return mint((x + P) % P);
	}
	mint operator^(ll e) {
		if (!e) return mint(1);
		mint r = *this ^ (e / 2); r = r * r;
		return e&1 ? *this * r : r;
	}
};

mint fac[N],inv[N];
mint ksm(mint u,int v){
	mint res=1;
	while(v){
		if(v&1)	res=(ll)res*u%P;
		v>>=1;	u=(ll)u*u%P;
	}
	return res;
}
mint C(int n,int m){
	if(n<m||m<0)	return mint(0);
	return fac[n]*inv[m]*inv[n-m];
}
mint S(int n,int m){
	mint res=0;
	for(int i=0;i<=m;++i){
		mint tmp=(ll)ksm(m-i,n)*inv[i]%P*inv[m-i]%P;
		if(i&1)	res=res-tmp;
		else	res=res+tmp;
	}
	return res;
}
void C_init(mint n){
	fac[0]=1;
	for(int i=1;i<=n;++i)	fac[i]=(ll)fac[i-1]*i%P;
	inv[n]=ksm(fac[n],P-2);
	for(int i=n;i>=1;--i)	inv[i-1]=(ll)inv[i]*i%P;
}

树状数组:

struct BIT
{
	int n;
	vector<int >c;
	BIT(){}
	BIT(int n){init(n);}
	void init(int n){this->n=n;c.resize(n+1,0);}
	void add(int u,int v){for(;u<=n;u+=u&-u)	c[u]=(c[u]+v)%P;}
	int ask(int u){int res=0;for(;u;u-=u&-u)	res=(res+c[u])%P;	return res;}
	void add(int l,int r,int v){add(l,v);	add(r+1,P-v);}
	int ask(int l,int r){return (ask(r)-ask(l-1)+P)%P;}
};
template<class T>
struct BIT
{
	int n;
	vector<T >c;
	BIT(){}
	BIT(int n){init(n);}
	void init(int n){this->n=n;c.resize(n+1,T{});}
	void add(int u,T v){for(;u<=n;u+=u&-u)	c[u]=c[u]+v;}
	T ask(int u){T res=0;for(;u;u-=u&-u)	res=res+c[u];	return res;}
	void add(int l,int r,T v){add(l,v);	add(r+1,-v);}
	T ask(int l,int r){return ask(r)-ask(l-1);}
	void clear(int u){for(;u<=n;u+=u&-u)	c[u]=T{};}
};

struct B{
	BIT<ll >T1,T2;
	//B(int n){T1.init(n),T2.init(n);}
	vector<int >c;
	void init(int n){
		T1.init(n);
		T2.init(n);
		c.resize(n+1,0);
	}
	void clear(int l,int r){
		T1.clear(l,r);
		T2.clear(l,r);
	}
	void add(int l,int r,ll v){
		v%=P;	r++;
		T1.add(l,v);
		T1.add(r,P-v);
		T2.add(l,(ll)v*(1-l+P)%P);
		T2.add(r,(ll)(P-v)*(1-r+P)%P);
	}
	int ask(int l,int r){
		l--;
		int A=T1.ask(r)%P*r%P;
		int B=T1.ask(l)%P*l%P;
		int C=T2.ask(r)%P;
		int D=T2.ask(l)%P;
		int AB=(A-B+P)%P;
		int CD=(C-D+P)%P;
		return (AB+CD)%P;
	}
}T1,T2;

ST表:

struct node{
	int n,s;
	vector<vector<int > >st;
	void init(int n,int val[]){
		this->n=n;
		this->s=log2(n);
		st.resize(n+1,vector(s+1,0));
		for(int i=1;i<=n;++i)	st[i][0]=val[i];
		for(int k=1;k<=s;++k){
			for(int i=1;i+(1<<k)-1<=n;++i){
				st[i][k]=max(st[i][k-1],st[i+(1<<(k-1))][k-1]);
			}
		}
	}
	int query(int l,int r){
		int k=log2(r-l+1);
		return max(st[l][k],st[r-(1<<k)+1][k]);
	}
}ST;

线段树:

#define ls u<<1
#define rs u<<1|1
#define ll long long 

const int N = 2e5 + 5;

struct Msg {
    ll sum; // 区间和
    int len; // 区间长度
    Msg() : sum(0), len(0) {}
    Msg(ll S, int L) : sum(S), len(L) {}
    
    Msg operator + (const Msg &p) const {
        return Msg(sum + p.sum, len + p.len);
    }
};

struct Tag {
    ll add; 
    Tag() : add(0) {}
    Tag(ll V) : add(V) {}
    
    operator bool() const { return add != 0; }
    
    Tag apply(const Tag &p) const {
        return Tag(add + p.add);
    }
    
    Msg apply(const Msg &m) const {
        return Msg(m.sum + add * m.len, m.len);
    }
};

Msg msg[N << 2];
Tag tag[N << 2];

void apply(int u, Tag t) {
    msg[u] = t.apply(msg[u]); 
    tag[u] = t.apply(tag[u]); 
}

void pushdown(int u) {
    if (!tag[u]) return;
    apply(ls, tag[u]);
    apply(rs, tag[u]);
    tag[u] = Tag(); 
}

void pushup(int u) {
    msg[u] = msg[ls] + msg[rs];
}

void build(int u, int l, int r) {
    tag[u] = Tag();
    if (l == r) {
        msg[u] = Msg(0, 1); 
        return;
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid);
    build(rs, mid + 1, r);
    pushup(u);
}

void modify(int u, int l, int r, int L, int R, Tag t) {
    if (L <= l && r <= R) {
        apply(u, t);
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(u);
    if (L <= mid) modify(ls, l, mid, L, R, t);
    if (R > mid) modify(rs, mid + 1, r, L, R, t);
    pushup(u);
}

Msg query(int u, int l, int r, int L, int R) {
    if (L <= l && r <= R) {
        return msg[u];
    }
    int mid = (l + r) >> 1;
    pushdown(u);
    
    Msg res = Msg(); 
    if (L <= mid) res = res + query(ls, l, mid, L, R);
    if (R > mid) res = res + query(rs, mid + 1, r, L, R);
    return res;
}


struct SMT//区间更新,区间最大值
{
	int n;
	vector<int >c1,c2;
	SMT(){}
	SMT(int n){init(n);}
	void init(int n){this->n=n;
		c1.clear();c1.resize(n<<2);
		c2.clear();c2.resize(n<<2);
	}
	void modify(int u,int l,int r,int L,int R,int x){
		c2[u]=max(c2[u],x);
		if(L<=l&&r<=R){c1[u]=max(c1[u],x);return ;}
		int mid=(l+r)>>1;
		if(L<=mid)	modify(ls,l,mid,L,R,x);
		if(R>mid)	modify(rs,mid+1,r,L,R,x);
	}
	int query(int u,int l,int r,int L,int R){
		if(L<=l&&r<=R)	return max(c1[u],c2[u]);
		int mid=(l+r)>>1;	int res=c1[u];
		if(L<=mid)	res=max(res,query(ls,l,mid,L,R));
		if(R>mid)	res=max(res,query(rs,mid+1,r,L,R));
		return res;
	}
}T;
struct SEGT{//单点修改,区间加,区间最大值
	ll mx[N],tag[N];
	void pushup(int u){
		mx[u]=max(mx[ls],mx[rs]);
	}
	void pushdown(int u){
		mx[ls]+=tag[u];	tag[ls]+=tag[u];
		mx[rs]+=tag[u];	tag[rs]+=tag[u];
		tag[u]=0;
	}
	void build(int u,int l,int r){
		mx[u]=-1e18;	tag[u]=0;
		if(l==r)	return ;
		int mid=(l+r)>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
	}
	void modify(int u,int l,int r,int x,ll v){//单点修改
		if(l==r){
			mx[u]=v;
			return ;
		}
		int mid=(l+r)>>1;	pushdown(u);
		if(x<=mid)	modify(ls,l,mid,x,v);
		else	modify(rs,mid+1,r,x,v);
		pushup(u);
	}
	void add(int u,int l,int r,int L,int R,ll v){//区间加
		if(L<=l&&r<=R){
			tag[u]+=v;
			mx[u]+=v;
			return ;
		}
		int mid=(l+r)>>1;	pushdown(u);
		if(L<=mid)	add(ls,l,mid,L,R,v);
		if(R>mid)	add(rs,mid+1,r,L,R,v);
		pushup(u);
	}
	ll query(int u,int l,int r,int L,int R){//区间最大值
	
		if(L<=l&&r<=R)	return mx[u];
		int mid=(l+r)>>1;	pushdown(u);	ll res=-1e18;
		if(L<=mid)	res=max(res,query(ls,l,mid,L,R));
		if(R>mid)	res=max(res,query(rs,mid+1,r,L,R));
		return res;
	}
}T;

并查集:

struct DSU {
    std::vector<int> f, siz;
    
    DSU() {}
    DSU(int n) {init(n);}
    
    void init(int n) {
        f.resize(n);
        std::iota(f.begin(), f.end(), 0);
        siz.assign(n, 1);
    }
    
    int find(int x) {
        while (x != f[x]) {
            x = f[x] = f[f[x]];
        }
        return x;
    }
    bool same(int x, int y) {
        return find(x) == find(y);
    }
    
    bool merge(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) {
            return false;
        }
        siz[x] += siz[y];
        f[y] = x;
        return true;
    }
    
    int size(int x) {
        return siz[find(x)];
    }
};

欧拉回路:

vector<int >G[N];
int t[N],top;
bool visp[N],vise[N];
void dfs(int u){
	t[top++]=u;
	if(visp[u])	return ;
	visp[u]=true;
	for(auto ed:G[u]){
		if(vise[ed])	continue;
		vise[ed]=true;
		dfs(sum[ed]^u);
		t[top++]=u;
	}
}
//最后top--

void euler(int u)
{
	while(!G[u].empty())
	{
		int w=G[u].back();
		G[u].pop_back();
		int v=edg[w]^u;
		if(!vis[w])	continue;
		vis[w]=false;
		euler(v);
	}
	cout<<u+1<<" ";
}

矩阵:

const int M=64;
struct Mat{
	ll mat[M][M];
	Mat(){memset(mat,0,sizeof(Mat));}
	void reset(){
		for(int i=0;i<M;++i)	mat[i][i]=1;
	}
	ll* operator [](ll p){return mat[p];}
	Mat operator *(const Mat &ot)const{
		Mat res; 
		for(int k=0;k<M;++k)
			for(int i=0;i<M;++i){
				if(!mat[i][k])	continue;
				for(int j=0;j<M;++j)
						res[i][j]=(res[i][j]+mat[i][k]*ot.mat[k][j])%P;	
			}
		return res;
	}
	Mat operator +(const Mat &ot)const{
		Mat res;
		for(int i=0;i<M;++i)
			for(int j=0;j<M;++j)
				res.mat[i][j]=(mat[i][j]+ot.mat[i][j])%P;	
		return res;
	}
};

矩阵求行列式

Z det(vector<vector<Z>> a) {
    int n = sz(a);
    Z res = 1;
    for (int i = 0; i < n; i++) {
        int k = i;
        while (k < n && a[k][i] == 0) k++;
        if (k == n) return Z(0);
        if (k != i) {
            swap(a[i], a[k]);
            res = -res; 
        }
        res *= a[i][i];
        Z inv = a[i][i].inv();
        for (int j = i + 1; j < n; j++) {
            if (a[j][i].v == 0) continue;
            Z div = a[j][i] * inv;
            for (int l = i; l < n; l++) {
                a[j][l] -= a[i][l] * div;
            }
        }
    }
    return res;
}

最大流/最小割:

template<class T>
struct MaxFlow {
    struct _Edge {
        int to;
        T cap;
        _Edge(int to, T cap) : to(to), cap(cap) {}
    };
    
    int n;
    std::vector<_Edge> e;
    std::vector<std::vector<int>> g;
    std::vector<int> cur, h;
    
    MaxFlow() {}
    MaxFlow(int n) {
        init(n);
    }
    
    void init(int n) {
        this->n = n;
        e.clear();
        g.assign(n, {});
        cur.resize(n);
        h.resize(n);
    }
    
    bool bfs(int s, int t) {
        h.assign(n, -1);
        std::queue<int> que;
        h[s] = 0;
        que.push(s);
        while (!que.empty()) {
            const int u = que.front();
            que.pop();
            for (int i : g[u]) {
                auto [v, c] = e[i];
                if (c > 0 && h[v] == -1) {
                    h[v] = h[u] + 1;
                    if (v == t) {
                        return true;
                    }
                    que.push(v);
                }
            }
        }
        return false;
    }
    
    T dfs(int u, int t, T f) {
        if (u == t) {
            return f;
        }
        auto r = f;
        for (int &i = cur[u]; i < int(g[u].size()); ++i) {
            const int j = g[u][i];
            //auto [v, c] = e[j];
            int v = e[j].to;
            T c = e[j].cap;
            if (c > 0 && h[v] == h[u] + 1) {
                auto a = dfs(v, t, std::min(r, c));
                e[j].cap -= a;
                e[j ^ 1].cap += a;
                r -= a;
                if (r == 0) {
                    return f;
                }
            }
        }
        return f - r;
    }
    void addEdge(int u, int v, T c) {
        g[u].push_back(e.size());
        e.emplace_back(v, c);
        g[v].push_back(e.size());
        e.emplace_back(u, 0);
    }
    T flow(int s, int t) {
        T ans = 0;
        while (bfs(s, t)) {
            cur.assign(n, 0);
            ans += dfs(s, t, std::numeric_limits<T>::max());
        }
        return ans;
    }
    
    std::vector<bool> minCut() {
        std::vector<bool> c(n);
        for (int i = 0; i < n; i++) {
            c[i] = (h[i] != -1);
        }
        return c;
    }
    
    struct Edge {
        int from;
        int to;
        T cap;
        T flow;
    };
    std::vector<Edge> edges() {
        std::vector<Edge> a;
        for (int i = 0; i < e.size(); i += 2) {
            Edge x;
            x.from = e[i + 1].to;
            x.to = e[i].to;
            x.cap = e[i].cap + e[i + 1].cap;
            x.flow = e[i + 1].cap;
            a.push_back(x);
        }
        return a;
    }
};

有源汇上下界最大流/最小流(结合上个模板一起食用)

template<class T>
struct LBoundSTFlow {
    struct EdgeRec { int u,v; T L,U; };
    int n, SS, TT, s_, t_;
    MaxFlow<T> mf;
    std::vector<EdgeRec> rec;
    std::vector<T> bal;
    int id_ts;

    LBoundSTFlow() {}
    LBoundSTFlow(int n_) { init(n_); }
    void init(int n_) {
        n = n_;
        SS = n;
        TT = n + 1;
        mf.init(n + 2);
        rec.clear();
        bal.assign(n, 0);
        id_ts = -1;
        s_ = t_ = -1;
    }
    void addEdge(int u,int v,T L,T U){
        rec.push_back({u,v,L,U});
    }

    void build_base() {
        mf.init(n + 2);
        bal.assign(n, 0);
        for (auto &e: rec) {
            mf.addEdge(e.u, e.v, e.U - e.L);
            bal[e.u] -= e.L;
            bal[e.v] += e.L;
        }
    }
    T add_demands_and_return_need() {
        T need = 0;
        for (int i = 0; i < n; ++i) {
            if (bal[i] > 0) { mf.addEdge(SS, i, bal[i]); need += bal[i]; }
            else if (bal[i] < 0) { mf.addEdge(i, TT, -bal[i]); }
        }
        return need;
    }
    bool feasible_with_ts(int s,int t,T capTS){
        s_=s; t_=t;
        build_base();
        T need = add_demands_and_return_need();
        id_ts = (int)mf.e.size();
        mf.addEdge(t, s, capTS);
        T got = mf.flow(SS, TT);
        return got == need;
    }

    std::pair<bool,T> maxflow(int s,int t){
        const T INF = std::numeric_limits<T>::max() / 4;
        if (!feasible_with_ts(s,t,INF)) return {false, (T)0};
        T base = mf.e[id_ts ^ 1].cap;
        mf.e[id_ts].cap = 0;
        mf.e[id_ts ^ 1].cap = 0;
        T extra = mf.flow(s, t);
        return {true, base + extra};
    }

    std::pair<bool,T> minflow(int s,int t){
        const T INF = std::numeric_limits<T>::max() / 4;
        if (!feasible_with_ts(s,t,INF)) return {false, (T)0};
        T base = mf.e[id_ts ^ 1].cap;
        mf.e[id_ts].cap = 0;
        mf.e[id_ts ^ 1].cap = 0;
        T can_reduce = mf.flow(t, s);
        return {true, base - can_reduce};
    }
};
//用法:先 init(n),对每条边 addEdge(u,v,L,U);然后 maxflow(s,t) 或 minflow(s,t)。
//返回:{ok, value},ok=false 表示无可行流。

最小费最大流:

template<class T>
struct MinCostFlow {
    struct _Edge {
        int to;
        T cap;
        T cost;
        _Edge(int to_, T cap_, T cost_) : to(to_), cap(cap_), cost(cost_) {}
    };
    int n;
    std::vector<_Edge> e;
    std::vector<std::vector<int>> g;
    std::vector<T> h, dis;
    std::vector<int> pre;

    bool dijkstra(int s, int t) {
        const T INF = std::numeric_limits<T>::max();
        dis.assign(n, INF);
        pre.assign(n, -1);
        std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int>>, std::greater<std::pair<T, int>>> que;
        dis[s] = 0;
        que.emplace(0, s);
        while (!que.empty()) {
            auto [d, u] = que.top();
            que.pop();
            if (dis[u] != d) continue;
            for (int i : g[u]) {
                int v = e[i].to;
                T cap = e[i].cap;
                T cost = e[i].cost;
                if (cap > 0) {
                    T nd = d + h[u] - h[v] + cost;
                    if (nd < dis[v]) {
                        dis[v] = nd;
                        pre[v] = i;
                        que.emplace(nd, v);
                    }
                }
            }
        }
        return dis[t] != INF;
    }

    bool spfa_init(int s) {
        const T INF = std::numeric_limits<T>::max();
        h.assign(n, INF);
        std::vector<char> inq(n, 0);
        std::queue<int> q;
        h[s] = 0;
        q.push(s);
        inq[s] = 1;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            inq[u] = 0;
            T hu = h[u];
            for (int i : g[u]) {
                if (e[i].cap <= 0) continue;
                int v = e[i].to;
                T w = e[i].cost;
                if (hu != INF && h[v] > hu + w) {
                    h[v] = hu + w;
                    if (!inq[v]) { q.push(v); inq[v] = 1; }
                }
            }
        }
        for (int i = 0; i < n; ++i) if (h[i] == INF) h[i] = 0;
        return true;
    }

    MinCostFlow() {}
    MinCostFlow(int n_) { init(n_); }
    void init(int n_) {
        n = n_;
        e.clear();
        g.assign(n, {});
    }
    void addEdge(int u, int v, T cap, T cost) {
        g[u].push_back(e.size());
        e.emplace_back(v, cap, cost);
        g[v].push_back(e.size());
        e.emplace_back(u, 0, -cost);
    }

    std::pair<T, T> flow(int s, int t) {
        T flow = 0, cost = 0;
        spfa_init(s);
        while (dijkstra(s, t)) {
            for (int i = 0; i < n; ++i) if (dis[i] != std::numeric_limits<T>::max()) h[i] += dis[i];
            T aug = std::numeric_limits<T>::max();
            for (int v = t; v != s; v = e[pre[v] ^ 1].to) aug = std::min(aug, e[pre[v]].cap);
            for (int v = t; v != s; v = e[pre[v] ^ 1].to) {
                e[pre[v]].cap -= aug;
                e[pre[v] ^ 1].cap += aug;
            }
            flow += aug;
            cost += aug * h[t];
        }
        return {flow, cost};
    }

    struct Edge {
        int from;
        int to;
        T cap;
        T cost;
        T flow;
    };
    std::vector<Edge> edges() {
        std::vector<Edge> a;
        for (int i = 0; i < (int)e.size(); i += 2) {
            Edge x;
            x.from = e[i + 1].to;
            x.to = e[i].to;
            x.cap = e[i].cap + e[i + 1].cap;
            x.cost = e[i].cost;
            x.flow = e[i + 1].cap;
            a.push_back(x);
        }
        return a;
    }
};
//时间复杂度:O(VE+F⋅(ElogV)) 
//前面是预处理势能的spfa时间复杂度
//后面是F(最大流)*每次dijkstra的E(边数)logV

点分治:

bool vis[N];
int siz[N],mx[N],root;
void get_root(int u,int tot){
	vis[u]=true;
	siz[u]=1;	mx[u]=0;
	for(auto v:G[u]){
		if(vis[v])	continue;
		get_root(v,tot);
		siz[u]+=siz[v];
		mx[u]=max(mx[u],siz[v]);
	}
	mx[u]=max(mx[u],tot-siz[u]);
	if(root==-1||mx[u]<mx[root])	root=u;
	vis[u]=false;
}
void dfs(int u){
	vis[u]=true;
	for(auto v:G[u]){
		if(vis[v])	continue;
		dfs(v);
	}
	vis[u]=false;
}
void dvq(int u,int tot){
	root=-1;
	get_root(u,tot);
	
	dfs(root);
	
	vis[root]=true;
	for(auto v:G[root]){
		if(vis[v])	continue;
		dvq(v,siz[v]<siz[root]? siz[v]:tot-siz[root]);
	}
}

点分树:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll rd() {
    ll x = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) { if (c == '-') f = 1; c = getchar(); }
    while (isdigit(c)) { x = x * 10 + (c - '0'); c = getchar(); }
    return f ? -x : x;
}
const int MAXN = 100000 + 5;
vector<int> g[MAXN];
int sz[MAXN], par_cent[MAXN], level_cent[MAXN], dist_cent[17][MAXN], ans[MAXN];
bool used[MAXN];
int n, m;

int dfs_sz(int u, int p) {
    sz[u] = 1;
    for (int v : g[u]) if (v != p && !used[v]) sz[u] += dfs_sz(v, u);
    return sz[u];
}

int get_centroid(int u, int p, int tot) {
    for (int v : g[u]) if (v != p && !used[v])
        if (sz[v] > tot / 2) return get_centroid(v, u, tot);
    return u;
}

void dfs_dist(int u, int p, int lvl, int d) {
    dist_cent[lvl][u] = d;
    for (int v : g[u]) if (v != p && !used[v]) dfs_dist(v, u, lvl, d + 1);
}

void build(int u, int p) {
    int tot = dfs_sz(u, -1);
    int c = get_centroid(u, -1, tot);
    par_cent[c] = (p == -1 ? c : p);
    level_cent[c] = (p == -1 ? 0 : level_cent[p] + 1);
    dfs_dist(c, -1, level_cent[c], 0);
    used[c] = true;
    for (int v : g[c]) if (!used[v]) build(v, c);
}

void update(int u) {
    for (int x = u; ; x = par_cent[x]) {
        ans[x] = min(ans[x], dist_cent[level_cent[x]][u]);
        if (x == par_cent[x]) break;
    }
}

int query(int u) {
    int res = INT_MAX;
    for (int x = u; ; x = par_cent[x]) {
        res = min(res, ans[x] + dist_cent[level_cent[x]][u]);
        if (x == par_cent[x]) break;
    }
    return res;
}

int main() {
    n = rd(); m = rd();
    for (int i = 1; i <= n; i++) {
        g[i].clear();
        used[i] = false;
    }
    for (int i = 1; i < n; i++) {
        int u = rd(), v = rd();
        g[u].push_back(v);
        g[v].push_back(u);
    }
    build(1, -1);
    const int INF = 1e9;
    for (int i = 1; i <= n; i++) ans[i] = INF;
    update(1);
    while (m--) {
        int t = rd(), v = rd();
        if (t == 1) update(v);
        else printf("%d\n", query(v));
    }
    return 0;
}

李超线段树:

struct Tree//李超树
{
	#define lc x<<1
	#define rc x<<1|1
	#define mid ((l+r)>>1)
	struct Node
	{
		ll a,b;
	}tree[600005];
	void ins(int x,int l,int r,ll a,ll b)//插入一个一次函数
	{
		if(tree[x].a*l+tree[x].b<=a*l+b&&tree[x].a*r+tree[x].b<=a*r+b)
		{
			tree[x].a=a,tree[x].b=b;
			return;
		}
		if(tree[x].a*l+tree[x].b>=a*l+b&&tree[x].a*r+tree[x].b>=a*r+b)return;
		if(tree[x].a*mid+tree[x].b<a*mid+b)swap(tree[x].a,a),swap(tree[x].b,b);
		if(a<tree[x].a)ins(lc,l,mid,a,b);
		else ins(rc,mid+1,r,a,b);//比较中间值,然后单边递归
	}
	void build(int x,int l,int r)
	{
		tree[x].a=tree[x].b=0;
		if(l==r)return;
		build(lc,l,mid);
		build(rc,mid+1,r);
	}
	ll query(int x,int l,int r,int p)//查询单点最大值,因为标记永久化所以需要一路取max
	{
		ll ans=tree[x].a*p+tree[x].b;
		if(l==r)return ans;
		if(p<=mid)ans=max(ans,query(lc,l,mid,p));
		else ans=max(ans,query(rc,mid+1,r,p));
		return ans;
	}
	#undef lc
	#undef rc
	#undef mid
}T;
//
struct LiChao {
    struct Line { ll m,b; Line(ll _m=0,ll _b=LLONG_MIN):m(_m),b(_b){} };
    struct Node { Line ln; Node *l,*r; Node(Line _ln):ln(_ln),l(nullptr),r(nullptr){} };
    ll L,R; Node* root;
    LiChao(ll _L,ll _R):L(_L),R(_R),root(nullptr){}
    ll f(const Line& ln,ll x){ return ln.m*x + ln.b; }
    void add(Line ln){ add_line(root,L,R,ln); }
    void add_line(Node*& o,ll l,ll r,Line ln){
        if(!o){ o=new Node(ln); return; }
        ll mid=(l+r)>>1;
        bool lef = f(ln,l) > f(o->ln,l);
        bool md  = f(ln,mid) > f(o->ln,mid);
        if(md) swap(ln, o->ln);
        if(l==r) return;
        if(lef != md) add_line(o->l, l, mid, ln);
        else          add_line(o->r, mid+1, r, ln);
    }
    ll query(ll x){ return query(root,L,R,x); }
    ll query(Node* o,ll l,ll r,ll x){
        if(!o) return LLONG_MIN;
        ll res = f(o->ln,x);
        if(l==r) return res;
        ll mid=(l+r)>>1;
        if(x<=mid) return max(res, query(o->l, l, mid, x));
        else       return max(res, query(o->r, mid+1, r, x));
    }
};

lichao.add(LiChao::Line(m,b));
lichao.query(a[i]);

几何:

struct Point{
	ll x,y;
	int u,v;
	Point(){}
	Point(ll X,ll Y){x=X;y=Y;}
	Point(ll X,ll Y,int U,int V){x=X;y=Y;u=U;v=V;}
	double theta(){
		return atan2(y,x)<0? pi+pi+atan2(y,x):atan2(y,x);
	}
	Point operator - (const Point &P)const{
		return Point(x-P.x,y-P.y);
	}
	Point operator + (const Point &P)const{
		return Point(x+P.x,y+P.y);
	}
	ll operator * (const Point &P)const{
		return x*P.y-y*P.x;
	}//叉积 (三角形面积的两倍) 
};

最近公共祖先LCA:

//树剖求LCA
int siz[N],dep[N],fa[N],mx_son[N];
int dfn[N],pre[N],top[N],tot;
int n,m,root,a[N];
vector<int >G[N];
void dfs1(int u,int f){
	fa[u]=f;siz[u]=1;dep[u]=dep[f]+1;mx_son[u]=0;
	for(auto v:G[u]){
		if(v==f)	continue;
		dfs1(v,u);siz[u]+=siz[v];
		if(siz[v]>siz[mx_son[u]])mx_son[u]=v;
	}
}
void dfs2(int u,int f,int t){
	top[u]=t;dfn[u]=++tot;pre[tot]=u;
	if(mx_son[u])	dfs2(mx_son[u],u,t);
	for(auto v:G[u])	if(v!=f&&v!=mx_son[u])	dfs2(v,u,v);
}
int LCA(int x,int y){
	for(;top[x]!=top[y];x=fa[top[x]])if(dep[top[x]]<dep[top[y]])swap(x,y);
	return dep[x]<dep[y]?x:y;
}


//倍增求LCA
void dfs1(int u,int f){
	fa[u]=f;	st[u][0]=f;	dep[u]=dep[f]+1;
	for(int k=1;k<20;++k)	st[u][k]=st[st[u][k-1]][k-1];
	for(auto v:G[u]){
		if(v==f)	continue;
		dfs1(v,u);
	}
}
int LCA(int x,int y){
	if(dep[x]<dep[y])	swap(x,y);
	for(int k=19;k>=0;--k)
		if((dep[x]-dep[y])>>k&1)	x=st[x][k];
	if(x==y)	return x;
	for(int k=19;k>=0;--k)
		if(st[x][k]!=st[y][k])	x=st[x][k],y=st[y][k];
	return st[x][0];
}

分块:

namespace block{
	int L[N],R[N],pos[N],B,tot;
	ll val[N],sum[N];
	void init(int n){
		B=max((int)sqrt(n),3);	tot=(n-1)/B+1;
		for(int i=1;i<=n;++i)	pos[i]=(i-1)/B+1;
		for(int i=1;i<=tot;++i)	L[i]=(i-1)*B+1,R[i]=min(n,i*B);
	}
	void modify(int p,int v){val[p]+=v;sum[pos[p]]+=v;}
	ll query(int l,int r){
		ll res=0;
		if(pos[l]==pos[r])	for(int i=l;i<=r;++i)	res+=val[i];
		else{
			for(int i=l;i<=R[pos[l]];++i)	res+=val[i];
			for(int i=pos[l]+1;i<pos[r];++i)	res+=sum[i];
			for(int i=L[pos[r]];i<=r;++i)	res+=val[i];
		}
		return res;
	}
}

字符串:

//双哈希
struct Hash {
    ll mod1 = 1000000007;
    ll mod2 = 1000000009;
    ll base1 = 131;
    ll base2 = 137;
    vector<ll> h1, h2, p1, p2;
    int n;
    Hash(const string &s) {
        n = s.size();
        h1.assign(n + 1, 0);
        h2.assign(n + 1, 0);
        p1.assign(n + 1, 1);
        p2.assign(n + 1, 1);
        for (int i = 1; i <= n; i++) {
            h1[i] = (h1[i - 1] * base1 + s[i - 1]) % mod1;
            h2[i] = (h2[i - 1] * base2 + s[i - 1]) % mod2;
            p1[i] = (p1[i - 1] * base1) % mod1;
            p2[i] = (p2[i - 1] * base2) % mod2;
        }
    }
    pair<ll, ll> get(int l, int r) {
        ll x1 = (h1[r] - h1[l - 1] * p1[r - l + 1]) % mod1;
        if (x1 < 0) x1 += mod1;
        ll x2 = (h2[r] - h2[l - 1] * p2[r - l + 1]) % mod2;
        if (x2 < 0) x2 += mod2;
        return {x1, x2};
    }
};
//AC自动机
namespace AC{
	int fail[N],trie[N][S],rt=1,tot=1;
	int insert(char *s){
		int len=strlen(s+1),cur=rt;
		for(int i=1;i<=len;++i){
			if(!trie[cur][s[i]-'a'])	trie[cur][s[i]-'a']=++tot;
			cur=trie[cur][s[i]-'a'];	nd[i]=cur;
		}
		return cur;
	}
	queue<int >q;
	void build(){
		for(int i=0;i<S;++i)	trie[0][i]=1;
		q.push(rt);
		while(!q.empty()){
			int u=q.front();	q.pop();
			for(int i=0;i<S;++i){
				int v=trie[u][i];
				if(!v)	trie[u][i]=trie[fail[u]][i];
				else	fail[v]=trie[fail[u]][i],q.push(v);
			}
		}
		for(int i=2;i<=tot;++i)	G[fail[i]].pub(i);
		dfs1(1,0);
		dfs2(1,0,1);
	}
}
//后缀数组
int sa[N], rk_[N], height[N];
int x_[N], y_[N], c[N];

void build_sa(const string &s){
    int n=sz(s), m=256;
    for(int i=1;i<=n;++i) x_[i]=(unsigned char)s[i-1]+1;
    for(int i=0;i<=m;++i) c[i]=0;
    for(int i=1;i<=n;++i) ++c[x_[i]];
    for(int i=1;i<=m;++i) c[i]+=c[i-1];
    for(int i=n;i>=1;--i) sa[c[x_[i]]--]=i;
    int p=0;
    for(int k=1;p<n;k<<=1){
        p=0;
        for(int i=n-k+1;i<=n;++i) y_[++p]=i;
        for(int i=1;i<=n;++i) if(sa[i]>k) y_[++p]=sa[i]-k;

        for(int i=0;i<=m;++i) c[i]=0;
        for(int i=1;i<=n;++i) ++c[x_[y_[i]]];
        for(int i=1;i<=m;++i) c[i]+=c[i-1];
        for(int i=n;i>=1;--i) sa[c[x_[y_[i]]]--]=y_[i];

        for(int i=1;i<=n;++i)   swap(x_[i],y_[i]);
        x_[sa[1]]=p=1;
        for(int i=2;i<=n;++i){
            int a=sa[i], b=sa[i-1];
            x_[a]=(y_[a]==y_[b] && (a+k<=n?y_[a+k]:0)==(b+k<=n?y_[b+k]:0))?p:++p;
        }
        m=p;
    }
    for(int i=1;i<=n;++i) rk_[sa[i]]=i;

    for(int i=1,k=0;i<=n;++i){
        if(rk_[i]==1){ k=0; continue; }
        int j=sa[rk_[i]-1];
        while(i+k<=n && j+k<=n && s[i-1+k]==s[j-1+k]) ++k;
        height[rk_[i]]=k;
        if(k) --k;
    }
}
    for(int i=1;i<=n;++i) cout<<sa[i]<<" \n"[i==n];
    for(int i=1;i<=n;++i) cout<<height[i]<<" \n"[i==n];
//后缀自动机
int n,m,las=1,tot=1;
int trip[N][26];
int len[N],fa[N];
ll val[N];
void insert(int u,int v)
{
	int p=las;	int np=las=++tot;	len[np]=len[p]+1;	val[np]=v;
	for(;p&&!trip[p][u];p=fa[p])	trip[p][u]=np;
	if(!p)	fa[np]=1;
	else
	{
		int q=trip[p][u];
		if(len[q]==len[p]+1)	fa[np]=q;
		else
		{
			int nq=++tot;	len[nq]=len[p]+1;
			fa[nq]=fa[q];	fa[q]=fa[np]=nq;
			memcpy(trip[nq],trip[q],sizeof(trip[q]));
			for(;p&&trip[p][u]==q;p=fa[p])	trip[p][u]=nq;
		}
	}
}

NTT:

struct Z{
    static const int MOD = 998244353;
    int v;
    Z(long long x=0){x %= MOD;if(x < 0) x += MOD;v = int(x);}
    operator long long() const { return v; }
    explicit operator int() const { return v; }

    Z& operator+=(const Z& o){v += o.v;if(v >= MOD) v -= MOD;return *this;}
    Z& operator-=(const Z& o){v -= o.v;if(v < 0) v += MOD;return *this;}
    Z& operator*=(const Z& o){v = int(1ll * v * o.v % MOD);return *this;}
    Z& operator/=(const Z& o){return *this *= o.inv();}

    friend Z operator+(Z a,const Z& b){ return a += b; }
    friend Z operator-(Z a,const Z& b){ return a -= b; }
    friend Z operator*(Z a,const Z& b){ return a *= b; }
    friend Z operator/(Z a,const Z& b){ return a /= b; }

    static Z qpow(Z a,long long e){Z r = 1;for(;e;e>>=1,a*=a) if(e&1) r *= a;return r;}
    Z inv() const { return qpow(*this, MOD-2); }
};

Z ksm(Z u,long long v){return Z::qpow(u,v);}
Z ksm(int u,long long v){return Z::qpow(Z(u),v);}

/******** NTT与多项式工具 ********/

void ntt(std::vector<Z>& a,bool inv){
    int n = (int)a.size();
    static std::vector<int> rev;
    static std::vector<Z> roots{0,1};
    if((int)rev.size() != n){
        int k = __lg(n);
        rev.assign(n,0);
        for(int i=0;i<n;i++){
            rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
        }
    }
    if((int)roots.size() < n){
        int k = __lg((int)roots.size());
        roots.resize(n);
        while((1<<k) < n){
            Z z = Z::qpow(3, (Z::MOD-1)>>(k+1));
            for(int i=(1<<(k-1)); i<(1<<k); i++){
                roots[2*i] = roots[i];
                roots[2*i+1] = roots[i] * z;
            }
            k++;
        }
    }
    for(int i=0;i<n;i++) if(i < rev[i]) std::swap(a[i],a[rev[i]]);
    for(int len=1; len<n; len<<=1){
        for(int i=0; i<n; i+=len<<1){
            for(int j=0; j<len; j++){
                Z u = a[i+j];
                Z v = a[i+j+len] * roots[len+j];
                a[i+j]      = u + v;
                a[i+j+len]  = u - v;
            }
        }
    }
    if(inv){
        std::reverse(a.begin()+1,a.end());
        Z invn = Z(n).inv();
        for(auto &x : a) x *= invn;
    }
}

std::vector<Z> convolution(std::vector<Z> a, std::vector<Z> b){
    if(a.empty() || b.empty()) return {};
    int need = (int)a.size() + (int)b.size() - 1;
    int n = 1;
    while(n < need) n <<= 1;
    a.resize(n);
    b.resize(n);
    ntt(a,false);
    ntt(b,false);
    for(int i=0;i<n;i++) a[i] *= b[i];
    ntt(a,true);
    a.resize(need);
    return a;
}

std::vector<Z> poly_add(const std::vector<Z>& a,const std::vector<Z>& b){
    std::vector<Z> c(std::max(a.size(),b.size()));
    for(size_t i=0;i<c.size();i++){
        Z x = 0, y = 0;
        if(i < a.size()) x = a[i];
        if(i < b.size()) y = b[i];
        c[i] = x + y;
    }
    return c;
}
std::vector<Z> poly_sub(const std::vector<Z>& a,const std::vector<Z>& b){
    std::vector<Z> c(std::max(a.size(),b.size()));
    for(size_t i=0;i<c.size();i++){
        Z x = 0, y = 0;
        if(i < a.size()) x = a[i];
        if(i < b.size()) y = b[i];
        c[i] = x - y;
    }
    return c;
}
std::vector<Z> mod_xk(std::vector<Z> a,int k){
    if((int)a.size() > k) a.resize(k);
    return a;
}
std::vector<Z> div_xk(const std::vector<Z>& a,int k){
    if(k >= (int)a.size()) return {};
    return std::vector<Z>(a.begin()+k,a.end());
}

using poly = std::vector<Z>;

/******** 组合数 ********/

Z fac[N], inv[N];

void C_init(int n){
    fac[0] = 1;
    for(int i=1;i<=n;i++) fac[i] = fac[i-1] * Z(i);
    inv[n] = fac[n].inv();
    for(int i=n;i>=1;i--) inv[i-1] = inv[i] * Z(i);
}

Z C(int n,int m){
    if(n < m || m < 0) return Z(0);
    return fac[n] * inv[m] * inv[n-m];
}

Z S(int n,int m){
    Z res = 0;
    for(int i=0;i<=m;i++){
        Z tmp = ksm(Z(m - i), n) * inv[i] * inv[m - i];
        if(i & 1) res -= tmp;
        else      res += tmp;
    }
    return res;
}

FWT:

void or_fwt(int *nw,int opt)
{
    for(int k=0;k<n;++k)
        for(int i=0;i<(1<<n);++i)
        {
            if(i&(1<<k))
            {
                if(opt==1)    nw[i]=(nw[i]+nw[i^(1<<k)])%P;
                else    nw[i]=(nw[i]-nw[i^(1<<k)]+P)%P;
            }
        }
}
void and_fwt(int *nw,int opt)
{
    for(int k=0;k<n;++k)
        for(int i=0;i<(1<<n);++i)
        {
            if((~i)&(1<<k))
            {
                if(opt==1)    nw[i]=(nw[i]+nw[i^(1<<k)])%P;
                else    nw[i]=(nw[i]-nw[i^(1<<k)]+P)%P;
            }
        }
}
void xor_fwt(int *nw,int opt)
{
    for(int k=0;k<n;++k)
        for(int i=0;i<(1<<n);++i)
        {
            if(i&(1<<k))
            {
                int x=nw[i^(1<<k)];    int y=nw[i];
                if(opt==1)    nw[i^(1<<k)]=(x-y+P)%P,nw[i]=(x+y)%P;
                else    nw[i^(1<<k)]=(ll)(x+y)*inv2%P,nw[i]=(ll)(y-x+P)*inv2%P;
            }
        }
}
void or_solve()
{
    for(int i=0;i<(1<<n);++i)    f[i]=a[i];
    for(int i=0;i<(1<<n);++i)    g[i]=b[i];
    or_fwt(f,1);    or_fwt(g,1);
    for(int i=0;i<(1<<n);++i)    h[i]=(ll)f[i]*g[i]%P;
    or_fwt(h,-1);
    for(int i=0;i<(1<<n);++i)    printf("%d ",h[i]);
    puts("");
}
void and_solve()
{
    for(int i=0;i<(1<<n);++i)    f[i]=a[i];
    for(int i=0;i<(1<<n);++i)    g[i]=b[i];
    and_fwt(f,1);    and_fwt(g,1);
    for(int i=0;i<(1<<n);++i)    h[i]=(ll)f[i]*g[i]%P;
    and_fwt(h,-1);
    for(int i=0;i<(1<<n);++i)    printf("%d ",h[i]);
    puts("");
}
void xor_solve()
{
    for(int i=0;i<(1<<n);++i)    f[i]=a[i];
    for(int i=0;i<(1<<n);++i)    g[i]=b[i];
    xor_fwt(f,1);    xor_fwt(g,1);
    for(int i=0;i<(1<<n);++i)    h[i]=(ll)f[i]*g[i]%P;
    xor_fwt(h,-1);
    for(int i=0;i<(1<<n);++i)    printf("%d ",h[i]);
    puts("");
}

高斯消元:

#include<bits/stdc++.h>
using namespace std;
int n;
double s[105][105];
bool flag;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n+1;j++)
			scanf("%lf",&s[i][j]);
	for(int i=1;i<=n;i++)
	{
		int tmp=i;
		for(int k=i+1;k<=n;k++)
			if(abs(s[k][i])>abs(s[tmp][i]))
				tmp=k;
		
		    for(int j=1;j<=n+1;j++)
			    swap(s[i][j],s[tmp][j]);
		for(int j=1;j<=n;j++)
		{
			if(j==i)
				continue;
			double tmp=s[j][i]/s[i][i];
			for(int k=1;k<=n+1;k++)
				s[j][k]-=s[i][k]*tmp;
		}
	}
	for(int i=1;i<=n;i++)
		if(s[i][i]==0)
			flag=true;
	if(flag)
	{
	    printf("No Solution");
	    return 0;
	}
	for(int i=1;i<=n;i++)
		printf("%.2lf\n",s[i][n+1]/s[i][i]);
	return 0;
}

扩展中国剩余定理:

ll exgcd(ll a, ll b, ll &x, ll &y) {
    // 终止情况:如果 b 为 0,则 gcd(a, b) = a,且 x = 1, y = 0
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }

    // 递归计算 gcd(b, a % b) 以及 x' 和 y'
    ll x1, y1;
    ll gcd = exgcd(b, a % b, x1, y1);

    // 回溯计算 x 和 y
    x = y1;
    y = x1 - (a / b) * y1;

    return gcd;
}
int main()
{
	ll A=1;	ll B=0;
	int T=rd();
	while(T--){
		ll a=rd();	ll b=rd();
		ll k1,k2;
		ll gcd=exgcd(A,a,k1,k2);
		if((b-B)%gcd)	return 0;//无解(题目保证有解)
		
		ll lcm=A/gcd*a;
		ll k=(b-B)/gcd;
		
		k=(k%lcm+lcm)%lcm;
		k1=(k1%lcm+lcm)%lcm;
		k2=(k2%lcm+lcm)%lcm;
		
		B=(B+ksc(ksc(k,k1,lcm),A,lcm))%lcm;
		A=lcm;
	}
	cout<<B;
	return 0;
}

莫比乌斯反演:

//给定 $N, M$,求 $1 \leq x \leq N$,$1 \leq y \leq M$ 且 $\gcd(x, y)$ 为质数的 $(x, y)$ 有多少对。

void init()
{
	mu[1]=1;
	for(int i=2;i<=10000000;++i)
	{
		if(!vis[i])	t[++top]=i,mu[i]=-1;
		for(int j=1;j<=top;++j)
		{
			if(t[j]*i>10000000)	break;
			vis[t[j]*i]=true;
			if(i%t[j]==0)	break;
			mu[t[j]*i]=-mu[i];
		}
	}
	for(int i=1;i<=top;++i)
		for(int j=1;j*t[i]<=10000000;++j)
			sum[j*t[i]]+=mu[j];
	for(int i=1;i<=10000000;++i)
		sum[i]+=sum[i-1];
}
int main()
{
	T=read();	init();
	while(T--)
	{
		n=read();	m=read();	ans=0;
		if(n>m)	swap(n,m);
		for(int l=1,r;l<=n;l=r+1)
		{
			r=min(n/(n/l),m/(m/l));
			ans+=(ll)(n/l)*(m/l)*(sum[r]-sum[l-1]);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

//欧拉筛,mu,phi
int mu[N];
int pre[N];
int phi[N];
int t[N],top;
vector<int >P[N];
inline void init(){
    mu[1]=1;    phi[1]=1;
    for(int i=2;i<N;i++){
        if(!pre[i]) pre[i]=i,mu[i]=-1,phi[i]=i-1,t[++top]=i;
        for(int j=1;j<=top&&t[j]*i<N;j++){
            pre[t[j]*i]=t[j];
            mu[t[j]*i]=mu[i]*(pre[i]==t[j]? 0:-1);
            phi[t[j]*i]=phi[i]*(pre[i]==t[j]? t[j]:t[j]-1);
        }
    }
    for(int i=1;i<N;++i)
        for(int j=i;j<N;j+=i)
            P[j].push_back(i);
}

线性基:

struct XB{
    int l,r;
    int a[20];
    int pos[20];
    XB(){
        l=r=0;
        memset(a,0,sizeof(a));
        memset(pos,0,sizeof(pos));
    }
    void insert(int x,int p){
        for(int i=19;i>=0;--i){
            if(!(x>>i&1))   continue;
            if(!a[i]){
                a[i]=x;
                pos[i]=p;
                break;
            }else{
                if(p<pos[i]){
                    swap(a[i],x);
                    swap(pos[i],p);
                }
                x^=a[i];
            }
        }
    }
    XB(int L,int R,int A){
        l=L;    r=R;
        memset(a,0,sizeof(a));
        memset(pos,0,sizeof(pos));
        insert(A,L);
    }
    int find(int x,int p){//查询某个数是线性基中第几大,从0开始
        if(x<0) return -1;
        int nw=-1;
        for(int i=0;i<=19;++i)
            if(a[i]&&pos[i]<=p)  nw++;
        int res=0;  int tmp=0;
        for(int i=19;i>=0;--i){
            if(!a[i]||pos[i]>p)   continue;
            if((tmp>>i&1)==(x>>i&1)){
                if(tmp>>i&1)    res+=1<<nw;
            }
            else{
                if((~tmp)>>i&1)    res+=1<<nw;
                tmp^=a[i];
            }
            nw--;
        }
        return res;
    }
    int kth(int x,int p){//查询线性基中第几大是谁,从0开始
        int nw=-1;
        for(int i=0;i<=19;++i)
            if(a[i]&&pos[i]<=p)  nw++;
        if(x>=(1<<(nw+1)))  return -1;
        int res=0;
        for(int i=19;i>=0;--i){
            if(!a[i]||pos[i]>p)   continue;
            if(x>>nw&1) res=max(res,res^a[i]);
            else    res=min(res,res^a[i]);
            nw--;
        }
        return res;
    }
};
posted @ 2019-05-17 11:12  Hevix  阅读(258)  评论(0)    收藏  举报