模板合集

快读

点击查看代码
template<typename type_of_scan>
inline void scan(type_of_scan &x){
	type_of_scan f = 1;x = 0;char s = getchar();
	while(s<'0'||s>'9'){if(s=='-')f = -1;s = getchar();}
	while(s>='0'&&s<='9'){x = x * 10 + s - '0';s = getchar();}
	x *= f;
}
template<typename type_of_print>
inline void print(type_of_print x){
	if(x<0)putchar('-') , x = -x;
	if(x>9)print(x/10);
	putchar(x%10+'0');
}

高精度

点击查看代码
bool check(string s1 , string s2){
	int len = s1.size() , len2 = s2.size();
	if(len<len2)return 1;
	if(len>len2)return 0;
	for(int i=0;i<len;i++){
		if(s1[i]<s2[i])return 1;
		if(s1[i]>s2[i])return 0;
	}
	return 0;
}
int s1[200005] , s2[200005] , s3[200005];
void init(){
	memset(s3,0,sizeof(s3));
	memset(s1,0,sizeof(s1));
	memset(s2,0,sizeof(s2));
}
struct big{
	string s;
	int len;
	bool down;
	big operator * (big B){//高精乘
		init();
		int len1 = len , len2 = B.len , len3 = len1 + len2;
		reverse(s.begin(),s.end()) , reverse(B.s.begin(),B.s.end());
		for(int i=0;i<len3;i++)s3[i] = 0 , s1[i] = (i < len1 ? s[i] - '0' : 0) , s2[i] = (i < len2 ? B.s[i] - '0' : 0);
		for(int i=0;i<len1;i++){
			for(int j=0;j<len2;j++){
				int c1 = s1[i] , c2 = s2[j];
				s3[i+j] += c1 * c2;
				s3[i+j+1] += (s3[i+j] / 10);
				s3[i+j] %= 10;
			}
		}
		while(len3>1&&s3[len3-1]==0)len3--;
		string ts = "";
		for(int i=0;i<len3;i++)ts += (s3[i] + '0');
		reverse(ts.begin(),ts.end());
		reverse(s.begin(),s.end());
		reverse(B.s.begin(),B.s.end());
		return {ts,len3,down^B.down};
	}
	big operator - (big B){//高精减
		init();
		big ans = {"",0,0};
		int len1 = len , len2 = B.len , len3 = max(len1,len2);
		bool sw = 0;
		if(check(s,B.s)){
			ans.down = 1 , sw = 1 , swap(s,B.s);
		}
		reverse(s.begin(),s.end()) , reverse(B.s.begin(),B.s.end());
		for(int i=0;i<len1;i++){
			s1[i] = s[i] - '0' , s2[i] = (i < len2 ? B.s[i] - '0' : 0);
		}
		for(int i=0;i<len1;i++){
			int c2 = s2[i];
			s1[i] -= c2;
			if(s1[i]<0)s1[i] += 10 , s1[i+1]--;
		}
		while(len3>1&&s1[len3-1]==0)len3--;
		string ts = "";
		for(int i=0;i<len3;i++)ts += (s1[i] + '0');
		reverse(ts.begin(),ts.end());
		reverse(s.begin(),s.end()) , reverse(B.s.begin(),B.s.end());
		if(sw)swap(s,B.s);
		ans.s = ts , ans.len = len3;
		return ans;
	}
	big operator + (big B){//高精加
		if((down^B.down)){
			big thi = {s,len,down};
			if(down){
				return B - thi;
			}else return thi - B;
		}
		int len1 = len , len2 = B.len , len3 = max(len1,len2) + 1;
		init();
		reverse(s.begin(),s.end()) , reverse(B.s.begin(),B.s.end());
		for(int i=0;i<len3;i++){
			s3[i] = 0;
			s1[i] = (i < len1 ? s[i] - '0' : 0);
			s2[i] = (i < len2 ? B.s[i] - '0' : 0);
		}
		for(int i=0;i<len3;i++){
			int c1 = s1[i] , c2 = s2[i];
			s3[i] += c1 + c2;
			s3[i+1] += (s3[i] / 10);
			s3[i] %= 10;
		}
		while(len3>1&&s3[len3-1]==0)len3--;
		string ts = "";
		for(int i=0;i<len3;i++)ts += (s3[i] + '0');
		reverse(ts.begin(),ts.end());
		reverse(s.begin(),s.end()) , reverse(B.s.begin(),B.s.end());
		return {ts,len3,down&B.down};
	}
}

CRT

点击查看代码
__int128 a[15] , b[15] , c[15] , n;
__int128 in(){
    __int128 k = 0 , f = 1;
    char c = getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f = -1;
        c = getchar();
    }
    while(c>='0'&&c<='9')k = k * 10 + c - '0' , c = getchar();
    return k * f;
}
void out(__int128 x){
    if(x<0)putchar('-') , x = -x;
    if(x<10)putchar(x+'0');
    else out(x/10) , putchar(x%10+'0');
}
void ex_gcd(__int128 a , __int128 b , __int128& x , __int128& y){  
	if(!b){
		x = 1;
		y = 0;
	}else{
		ex_gcd(b,a%b,y,x);
		y -= a / b * x;
	}
}
__int128 inverse(__int128 a , __int128 m){
	__int128 x , y;
	ex_gcd(a,m,x,y);
	return (x % m + m) % m;
}
__int128 CRT(){
	__int128 suma = 1;
	for(__int128 i=1;i<=n;i++)suma *= a[i];
	for(__int128 i=1;i<=n;i++){
		__int128 m = suma / a[i];
		c[i] = m * inverse(m,a[i]);
	}
	__int128 ans = 0;
	for(__int128 i=1;i<=n;i++)ans += c[i] * b[i] , ans %= suma;
	return ans;
}

最大流

点击查看代码

int dis[40005] , flow[4000005] , cnt , head[40005] , s , t = 40001;
int n , m , cur[40005] , k , sum;
struct edge{
    int to , nxt , mxfl;
}ed[4000005];
void init(){
    memset(head,-1,sizeof(head));
    cnt = 0;
}
void add_edge(int u , int v , int w){
    ed[cnt].to = v , ed[cnt].nxt = head[u] , ed[cnt].mxfl = w , head[u] = cnt , cnt++;
    ed[cnt].to = u , ed[cnt].nxt = head[v] , ed[cnt].mxfl = 0 , head[v] = cnt , cnt++;
}
bool bfs(){
    memset(dis,0,sizeof(dis));
    queue<int> q;q.push(s);dis[s]=1;
    while(!q.empty()){
        int u = q.front();q.pop();
        for(int i=head[u];~i;i=ed[i].nxt){
            int v = ed[i].to;
            if(!dis[v]&&ed[i].mxfl>flow[i]){
                dis[v] = dis[u] + 1;
                q.push(v);
            }
        }
    }
    return dis[t] > 0;
}
int dfs(int u , int f){
    if(u==t)return f;
    if(f==0)return 0;
    int ret = 0;
    for(int &i=cur[u];~i;i=ed[i].nxt){
        int v = ed[i].to , d;
        if(dis[v]==dis[u]+1&&(d=dfs(v,min(f-ret,ed[i].mxfl-flow[i])))){
            ret += d , flow[i] += d , flow[i^1] -= d;
            if(ret==f)return ret;
        }
    }
    return ret;
}
int dinic(){
    int maxflow = 0;
    while(bfs()){
        memcpy(cur,head,sizeof(head));
        maxflow += dfs(s,1e18);
    }
    return maxflow;
}

最小费用最大流

点击查看代码
int n , m , tot = 1 , lnk[N] , cur[N] , ter[M] , nxt[M] , cap[M] , cost[M] , dis[N] , ret;
bool vis[N];
void add(int u, int v, int w, int c) {
    ter[++tot] = v , nxt[tot] = lnk[u] , lnk[u] = tot , cap[tot] = w , cost[tot] = c;
}
void addedge(int u , int v , int w , int c){add(u,v,w,c) , add(v,u,0,-c);}
bool spfa(int s, int t){
    memset(dis,0x3f,sizeof(dis));
    memcpy(cur,lnk,sizeof(lnk));
    std::queue<int> q;
    q.push(s) , dis[s] = 0 , vis[s] = true;
    while(!q.empty()){
        int u = q.front();
        q.pop() , vis[u] = false;
        for(int i=lnk[u];i;i=nxt[i]){
            int v = ter[i];
            if(cap[i]&&dis[v]>dis[u]+cost[i]){
                dis[v] = dis[u] + cost[i];
                if(!vis[v])q.push(v) , vis[v] = true;
            }
        }
    }
    return dis[t] != INF;
}
int dfs(int u , int t , int flow){
    if(u==t)return flow;
    vis[u] = true;
    int ans = 0;
    for(int &i=cur[u];i&&ans<flow;i=nxt[i]){
        int v = ter[i];
        if(!vis[v]&&cap[i]&&dis[v]==dis[u]+cost[i]){
            int x = dfs(v,t,std::min(cap[i],flow-ans));
            if(x)ret += x * cost[i] , cap[i] -= x , cap[i^1] += x , ans += x;
        }
    }
    vis[u] = false;
    return ans;
}
int mcmf(int s , int t){
    int ans = 0;
    while(spfa(s,t)){
        int x;
        while((x=dfs(s,t,INF)))ans += x;
    }
    return ans;
}

树状树组

点击查看代码
int bit[500005];
int lowbit(int x){
	return x & (-x);
}
void add(int i , int x){
	for(;i<=n;i+=lowbit(i))bit[i] += x;
}
int search(int x){
	int ans = 0;
	for(;x>0;x-=lowbit(x))ans += bit[x];
	return ans;
}

KMP

点击查看代码
vector<int> work(string s){
    int len = s.size();
    vector<int> p(len);
    for(int i=1,j=0;i<len;i++){
        j = p[i-1];
        while(j&&s[i]!=s[j])j = p[j-1];
        if(s[i]==s[j])j++;
        p[i] = j;
    }
    return p;
}
vector<int> KMP(){
    string s = s2 + '#' + s1;
    int l1 = s1.size() , l2 = s2.size();
    vector<int> p = work(s) , ans;
    for(int i=l2+1;i<=l1+l2;i++){
        if(p[i]==l2)ans.push_back(i-2*l2);
    }
    return ans;
}

LCA

点击查看代码
int st[500005][19] , dfn[500005] , n , m , root , df;
vector<int> vec[500005];
int get(int x , int y){
	return (dfn[x] < dfn[y] ? x : y);
}
void dfs(int u , int fa){
	st[dfn[u]=++df][0] = fa;
	for(int i=0;i<vec[u].size();i++){
		if(vec[u][i]==fa)continue;
		dfs(vec[u][i],u);
	}
}
int lca(int u , int v){
	if(u==v)return u;
	if((u=dfn[u])>(v=dfn[v]))swap(u,v);
	int d = __lg(v-u++);
	return get(st[u][d],st[v-(1<<d)+1][d]);
}
void init(){
	dfs(root,0);
	for(int j=1;j<=__lg(n);j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			st[i][j] = get(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	}
}

tarjan求SCC

点击查看代码
int low[100005] , dfn[10005] , s[10005] , num[10005] , dfncnt;
int sc , sz[10005] , n , m , d[10005] , dp[10005] , tp , color[100005];
vector<int> g[10005] , vec[10005];
struct node{
	int u , v;
};
vector<node> edge;
bool in_stack[10005];
void tarjan(int u){
	low[u] = dfn[u] = ++dfncnt , s[++tp] = u , in_stack[u] = 1;
	for(int i=0;i<g[u].size();i++){
	    int v = g[u][i];
	    if(!dfn[v]){
	    	tarjan(v);
	    	low[u] = min(low[u],low[v]);
	    }else if(in_stack[v]){
	    	low[u] = min(low[u],dfn[v]);
	    }
	}
	if(dfn[u]==low[u]){
		++sc;
		do{
			color[s[tp]] = sc;
			sz[sc]++;
			in_stack[s[tp]] = 0;
		}while(s[tp--]!=u);
	}
}

树剖

点击查看代码
int n , m , dep[200005] , siz[200005] , son[200005] , dfn[200005] , dfncnt , fa[200005];
int w[200005] , top[200005] , rnk[200005];
vector<pair<int,int> > vec[200005] , edge;
void dfs1(int u , int f){
	fa[u] = f , dep[u] = dep[f] + 1 , siz[u] = 1;
	for(pair<int,int> ed:vec[u]){
		int v = ed.first;
		if(v==f)continue;
		w[v] = ed.second;
		dfs1(v,u);
		siz[u] += siz[v];
		if(siz[son[u]]<siz[v])son[u] = v;
	}
}
void dfs2(int u , int tp){
	top[u] = tp , dfn[u] = ++dfncnt , rnk[dfncnt] = u;
	if(son[u])dfs2(son[u],tp);
	for(pair<int,int> ed:vec[u]){
		int v = ed.first;
		if(v!=fa[u]&&v!=son[u])dfs2(v,v);
	}
}
void solve_change(int u , int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		add(1,dfn[top[u]],dfn[u]);
		u = fa[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	add(1,dfn[v]+1,dfn[u]);
}
int solve_sum(int u , int v){
	int sum = 0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		sum += query_sum(1,dfn[top[u]],dfn[u]);
		u = fa[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	sum += query_sum(1,dfn[v]+1,dfn[u]);
	return sum;
}

tarjan求割点

点击查看代码
int n , m;
int dfn[100005] , low[100005] , idx , res;
bool vis[100005] , flag[100005];
vector<int> edge[100005];
void tarjan(int u , int fa){
	dfn[u] = low[u] = ++idx , vis[u] = true;
	int child = 0;
	for(int v:edge[u]){
		if(!vis[v]){
			child++;
			tarjan(v,u);
			low[u] = min(low[u],low[v]);
			if(fa!=u&&low[v]>=dfn[u]&&!flag[u]){
				flag[u] = true , res++;
			}
		}else if(v!=fa){
			low[u] = min(low[u],dfn[v]);
		}
	}
	if(fa==u&&child>=2&&!flag[u]){
		flag[u] = true , res++;
	}
}

manacher

点击查看代码
void manacher(string s){
	string s2 = "#";
	for(int i=0;i<n;i++)s2 += s[i] , s2 += "#";
	n = s2.size();
	for(int i=0,l=0,r=-1;i<n;i++){
		int k = (i > r) ? 1 : min(d[l+r-i],r-i+1);
		while(i-k>=0&&i+k<n&&s2[i-k]==s2[i+k])k++;
		d[i] = k--;
		if(i+k>r)r = i + k , l = i - k;
	}
	for(int i=0;i<n;i++)ansn = max(ansn,d[i]);
}

后缀排序

点击查看代码
void sort_sa(){
    for(int i=1;i<=n;i++)cnt[rk[i]=s[i]]++;
    for(int i=1;i<=m;i++)cnt[i] += cnt[i-1];
    for(int i=n;i>=1;i--)sa[cnt[rk[i]]--] = i;
    for(int w=1;;w<<=1,m=p){
        int cur = 0;
        for(int i=n-w+1;i<=n;i++)id[++cur] = i;
        for(int i=1;i<=n;i++)if(sa[i]>w)id[++cur] = sa[i] - w;
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++)cnt[rk[i]]++;
        for(int i=1;i<=m;i++)cnt[i] += cnt[i-1];
        for(int i=n;i>=1;i--)sa[cnt[rk[id[i]]]--] = id[i];
        p = 0;
        memcpy(oldrk,rk,sizeof(oldrk));
        for(int i=1;i<=n;i++){
            if(oldrk[sa[i]]==oldrk[sa[i-1]]&&oldrk[sa[i]+w]==oldrk[sa[i-1]+w])rk[sa[i]] = p;
            else rk[sa[i]] = ++p;
        }
        if(p==n)break;
    }
}

线性基

点击查看代码
int a[60];
void add(int x){
	for(int i=60;~i;i--){
		if((x>>i)&1){
			if(!a[i]){
				a[i] = x;
				return;
			}else x ^= a[i];
		}
	}
} 
int query(){
	int x = 0;
	for(int i=60;~i;i--){
		x = max(x,x^a[i]);
	}
	return x;
}

李超线段树

点击查看代码
double eps = 1e-9;
int cmp(double x , double y){
	if(x-y>eps)return 1;
	if(y-x>eps)return -1;
	return 0;
}
struct line{
	double k , b;
}p[100005];
int s[160005] , cnt;
double calc(int id , int d){
	return p[id].b + p[id].k * d;
}
void add(int x0 , int y0 , int x1 , int y1){
	cnt++;
	if(x0==x1)p[cnt].k = 0 , p[cnt].b = max(y0,y1);
	else p[cnt].k = 1.0 * (y1 - y0) / (x1 - x0) , p[cnt].b = y0 - p[cnt].k * x0;
}
void upd(int root , int cl , int cr , int u){
	int &v = s[root] , mid = (cl + cr) >> 1;
	int bmid = cmp(calc(u,mid),calc(v,mid));
	if(bmid==1||(!bmid&&u<v))swap(u,v);
	int bl = cmp(calc(u,cl),calc(v,cl)) , br = cmp(calc(u,cr),calc(v,cr));
	if(bl==1||(!bl&&u<v))upd(root<<1,cl,mid,u);
	if(br==1||(!br&&u<v))upd(root<<1|1,mid+1,cr,u);
}
void update(int root , int cl , int cr , int l , int r , int u){
	if(l<=cl&&cr<=r){
		upd(root,cl,cr,u);
		return;
	}
	int mid = (cl + cr) >> 1;
	if(l<=mid)update(root<<1,cl,mid,l,r,u);
	if(mid<r)update(root<<1|1,mid+1,cr,l,r,u);
}
pair<double,int> pmax(pair<double,int> x , pair<double,int> y){
	if(cmp(x.first,y.first)==-1)return y;
	else if(cmp(x.first,y.first)==1)return x;
	else return x.second < y.second ? x : y;
}
pair<double,int> query(int root , int l , int r , int d){
	if(r<d||d<l)return {0,0};
	int mid = (l + r) >> 1;
	double res = calc(s[root],d);
	if(l==r)return {res,s[root]};
	return pmax({res,s[root]},pmax(query(root<<1,l,mid,d),query(root<<1|1,mid+1,r,d)));
}

动态开点线段树+线段树合并

点击查看代码
struct segtree{
	int l , r , ls , rs , num , maxid;
};
vector<segtree> tree;
segtree push_up(int i){
	segtree s = {tree[i].l,tree[i].r,tree[i].ls,tree[i].rs,0,0};
	if(tree[i].ls){
		if(tree[tree[i].ls].num>s.num)s.maxid = tree[tree[i].ls].maxid;
		s.num = max(s.num,tree[tree[i].ls].num);
	}
	if(tree[i].rs){
		if(tree[tree[i].rs].num>s.num)s.maxid = tree[tree[i].rs].maxid;
		s.num = max(s.num,tree[tree[i].rs].num);
	}
	return s;
}
void update(int i , int x , int k){
	if(tree[i].l==tree[i].r){
		tree[i].num += k , tree[i].maxid = tree[i].l;
		return;
	}
	int mid = (tree[i].l + tree[i].r) >> 1;
	if(mid>=x){
		if(!tree[i].ls){
			tree.push_back({tree[i].l,mid,0,0,0,0});
			tree[i].ls = tree.size() - 1;
		}
		update(tree[i].ls,x,k);
	}else{
		if(!tree[i].rs){
			tree.push_back({mid+1,tree[i].r,0,0,0,0});
			tree[i].rs = tree.size() - 1;
		}
		update(tree[i].rs,x,k);
	}
	tree[i] = push_up(i);
}
int merge(int i1 , int i2){
	if(!i1)return i2;
	if(!i2)return i1;
	if(tree[i1].l==tree[i1].r){
		tree[i1].num += tree[i2].num , tree[i1].maxid = tree[i1].l;
		return i1;
	}
	tree[i1].ls = merge(tree[i1].ls,tree[i2].ls);
	tree[i1].rs = merge(tree[i1].rs,tree[i2].rs);
	tree[i1] = push_up(i1);
	return i1;
}

HLPP(最大流)

点击查看代码
struct qxx{
    int nex , t;
    long long v;
}e[240005];
int h[1205] , cnt = 1;
void add_path(int f , int t , long long w){
    e[++cnt] = {h[f],t,w} , h[f] = cnt;
}
void add_flow(int f , int t , long long v){
    add_path(f,t,v) , add_path(t,f,0);
}
int ht[1205];
long long ex[1205];
int gap[1205];
stack<int> B[1205];
int level = 0;
int push(int u){
	bool init = u == s;
	for(int i=h[u];i;i=e[i].nex){
		const int &v = e[i].t;const long long &w = e[i].v;
		if(!w||(init==false&&ht[u]!=ht[v]+1)||ht[v]==INF)continue;
		long long k = init ? w : min(w,ex[u]);
		if(v!=s&&v!=t&&!ex[v])B[ht[v]].push(v) , level = max(level,ht[v]);
		ex[u] -= k , ex[v] += k , e[i].v -= k , e[i^1].v += k;
		if(!ex[u])return 0;
	}
	return 1;
}
void relabel(int u){
	ht[u] = INF;
	for(int i=h[u];i;i=e[i].nex)if(e[i].v)ht[u] = min(ht[u],ht[e[i].t]);
	if(++ht[u]<n){
		B[ht[u]].push(u);
		level = max(level,ht[u]);
		++gap[ht[u]];
	}
}
bool bfs_init(){
	memset(ht,0x3f,sizeof(ht));
	queue<int> q;
	q.push(t) , ht[t] = 0;
	while(q.size()){
		int u = q.front();
		q.pop();
		for(int i=h[u];i;i=e[i].nex){
			const int &v = e[i].t;
			if(e[i^1].v&&ht[v]>ht[u]+1)ht[v] = ht[u] + 1 , q.push(v);
		}
	}
	return ht[s] != INF;
}
int select(){
	while(level>-1&&B[level].size()==0)level--;
	return level == -1 ? 0 : B[level].top();
}
long long hlpp(){
	if(!bfs_init())return 0;
	memset(gap,0,sizeof(gap));
	for(int i=1;i<=n;i++)if(ht[i]!=INF)gap[ht[i]]++;
	ht[s] = n;
	push(s);
	int u;
	while((u=select())){
		B[level].pop();
		if(push(u)){
			if(!--gap[ht[u]]){
				for(int i=1;i<=n;i++){
					if(i!=s&&ht[i]>ht[u]&&ht[i]<n+1)ht[i] = n + 1;
				}
			}
			relabel(u);
		}
	}
	return ex[t];
}

笛卡尔树

点击查看代码
int w[10000005] , stk[10000005] , k , n , top;
int ls[10000005] , rs[10000005];
void build(){
	for(int i=1;i<=n;i++){
		int k = top;
		while(k>0&&w[stk[k]]>w[i])k--;
		if(k)rs[stk[k]] = i;
		if(k<top)ls[i] = stk[k+1];
		stk[++k] = i;
		top = k;
	}
}

吉司机线段树(支持历史最值,不支持取max)

点击查看代码
struct segment{
	int l , r , sum , se , cnt , maxa , maxb;
	int add1 , add2 , add3 , add4;
}tree[2000005];
int n , m;
void push_up(int i){
	tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum , tree[i].maxa = max(tree[i<<1].maxa,tree[i<<1|1].maxa);
	tree[i].maxb = max(tree[i<<1].maxb,tree[i<<1|1].maxb);
	if(tree[i<<1].maxa==tree[i<<1|1].maxa){
		tree[i].cnt = tree[i<<1].cnt + tree[i<<1|1].cnt , tree[i].se = max(tree[i<<1].se,tree[i<<1|1].se);
	}else if(tree[i<<1].maxa>tree[i<<1|1].maxa){
		tree[i].cnt = tree[i<<1].cnt , tree[i].se = max(tree[i<<1].se,tree[i<<1|1].maxa);
	}else{
		tree[i].cnt = tree[i<<1|1].cnt , tree[i].se = max(tree[i<<1|1].se,tree[i<<1].maxa);
	}
}
void change(int i , int k1 , int k2 , int k3 , int k4){
	tree[i].sum += k1 * tree[i].cnt + k2 * (tree[i].r - tree[i].l + 1 - tree[i].cnt);
	tree[i].maxb = max(tree[i].maxb,tree[i].maxa+k3) , tree[i].maxa += k1;
	if(tree[i].se!=-2e9)tree[i].se += k2;
	tree[i].add3 = max(tree[i].add1+k3,tree[i].add3);
	tree[i].add4 = max(tree[i].add2+k4,tree[i].add4);
	tree[i].add1 += k1 , tree[i].add2 += k2;
}
void push_down(int i){
	int maxn = max(tree[i<<1].maxa,tree[i<<1|1].maxa);
	if(tree[i<<1].maxa==maxn)change(i<<1,tree[i].add1,tree[i].add2,tree[i].add3,tree[i].add4);
	else change(i<<1,tree[i].add2,tree[i].add2,tree[i].add4,tree[i].add4);
	if(tree[i<<1|1].maxa==maxn)change(i<<1|1,tree[i].add1,tree[i].add2,tree[i].add3,tree[i].add4);
	else change(i<<1|1,tree[i].add2,tree[i].add2,tree[i].add4,tree[i].add4);
	tree[i].add1 = tree[i].add2 = tree[i].add3 = tree[i].add4 = 0;
}
void build(int i , int l , int r){
	tree[i].l = l , tree[i].r = r;
	if(l==r){
		cin >> tree[i].sum;tree[i].maxa = tree[i].maxb = tree[i].sum;
		tree[i].se = -2e9 , tree[i].cnt = 1;
		return;
	}
	int mid = (l + r) >> 1;
	build(i<<1,l,mid) , build(i<<1|1,mid+1,r);
	push_up(i);
}
void update_add(int i , int l , int r , int k){
	if(tree[i].l>=l&&tree[i].r<=r){
		tree[i].sum += (tree[i].r - tree[i].l + 1) * k , tree[i].maxa += k , tree[i].maxb = max(tree[i].maxa,tree[i].maxb);
		if(tree[i].se!=-2e9)tree[i].se += k;
		tree[i].add1 += k , tree[i].add2 += k;
		tree[i].add3 = max(tree[i].add3,tree[i].add1) , tree[i].add4 = max(tree[i].add4,tree[i].add2);
		return;
	}
	push_down(i);
	if(tree[i<<1].r>=l)update_add(i<<1,l,r,k);
	if(tree[i<<1|1].l<=r)update_add(i<<1|1,l,r,k);
	push_up(i);
}
void update_min(int i , int l , int r , int k){
	if(tree[i].maxa<=k)return;
	else if(k>tree[i].se&&tree[i].l>=l&&tree[i].r<=r){
		tree[i].sum -= (tree[i].maxa - k) * tree[i].cnt;
		tree[i].add1 -= (tree[i].maxa - k) , tree[i].maxa = k;
	}else{
		push_down(i);
		if(tree[i<<1].r>=l)update_min(i<<1,l,r,k);
		if(tree[i<<1|1].l<=r)update_min(i<<1|1,l,r,k);
		push_up(i);
	}
}
int query_sum(int i , int l , int r){
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].sum;
	push_down(i);int sum = 0;
	if(tree[i<<1].r>=l)sum += query_sum(i<<1,l,r);
	if(tree[i<<1|1].l<=r)sum += query_sum(i<<1|1,l,r);
	return sum;
}
int query_maxa(int i , int l , int r){
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].maxa;
	push_down(i);int sum = -2e9;
	if(tree[i<<1].r>=l)sum = max(sum,query_maxa(i<<1,l,r));
	if(tree[i<<1|1].l<=r)sum = max(sum,query_maxa(i<<1|1,l,r));
	return sum;
}
int query_maxb(int i , int l , int r){
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].maxb;
	push_down(i);int sum = -2e9;
	if(tree[i<<1].r>=l)sum = max(sum,query_maxb(i<<1,l,r));
	if(tree[i<<1|1].l<=r)sum = max(sum,query_maxb(i<<1|1,l,r));
	return sum;
}

逆元(\(n\) 个任意数)

点击查看代码
int n, p, k, a[MAXN];
int s[MAXN], t[MAXN];
int qpow(int a , int b){
	if(!b){
		return 1;
	}
	int c = qpow(a,b/2);
	c = 1ll * c * c % p;
	if(b%2){
		c = 1ll * c * a % p;
	}
	return c;
}
void init(){
	s[0] = 1;
	for(int i=1;i<=n;++i){
		s[i] = 1ll * s[i-1] * a[i] % p;
	}
	t[n] = qpow(s[n],p-2);
	for(int i=n-1;i>=1;--i){
		t[i] = 1ll * t[i+1] * a[i+1] % p;
	}
	int powk = 1, ans = 0;
	for(int i=1;i<=n;++i){
		powk = 1ll * powk * k % p;
		ans = (ans + 1ll * powk * s[i-1] % p * t[i]) % p;
	}
}

可持久化线段树(静态区间第 \(k\) 小)

点击查看代码
struct tree{
	int l , r , sum , ls , rs;
}tree[200005<<5];
int build(int l , int r){
	int id = ++tot;
	tree[id] = {l,r,0};
	if(l==r)return id;
	int mid = (l + r) >> 1;
	tree[id].ls = build(l,mid) , tree[id].rs = build(mid+1,r);
	return id;
}
int update(int i , int k){
	int id = ++tot;
	tree[id] = tree[i] , tree[id].sum++;
	if(tree[i].l==tree[i].r)return id;
	if(tree[tree[i].ls].r>=k)tree[id].ls = update(tree[i].ls,k);
	else tree[id].rs = update(tree[i].rs,k);
	return id;
}
int query(int u , int v , int k){
	if(tree[u].l==tree[u].r)return tree[u].l;
	int x = tree[tree[u].ls].sum - tree[tree[v].ls].sum;
	if(k<=x)return query(tree[u].ls,tree[v].ls,k);
	else return query(tree[u].rs,tree[v].rs,k-x);
}

可持久化线段树(支持插入,删除,全局第 \(k\) 小,\(x\) 的排名,\(x\) 的前驱后继)

点击查看代码
struct tree{
	int l , r , sum , ls , rs;
}tree[500005<<5];
struct query{
	int op , id , x;
}q[500005];
int build(int l , int r){
	int id = ++tot;
	tree[id] = {l,r,0};
	if(l==r){
        if(l==1)tree[id].sum = 1;
        else if(l==len)tree[id].sum = 1;
        return id;
    }
	int mid = (l + r) >> 1;
	tree[id].ls = build(l,mid) , tree[id].rs = build(mid+1,r);
    tree[id].sum = tree[tree[id].ls].sum + tree[tree[id].rs].sum;
	return id;
}
int update_add(int i , int k){
	int id = ++tot;
	tree[id] = tree[i] , tree[id].sum++;
	if(tree[i].l==tree[i].r)return id;
	if(tree[tree[i].ls].r>=k)tree[id].ls = update_add(tree[i].ls,k);
	else tree[id].rs = update_add(tree[i].rs,k);
	return id;
}
int update_del(int i , int k){
    int id = ++tot;
    tree[id] = tree[i];
    if(tree[i].l==tree[i].r){
        if(tree[id].sum>0)tree[id].sum--;
        return id;
    }
	if(tree[tree[i].ls].r>=k)tree[id].ls = update_del(tree[i].ls,k);
	else tree[id].rs = update_del(tree[i].rs,k);
    tree[id].sum = tree[tree[id].ls].sum + tree[tree[id].rs].sum;
    return id;
}
int query_kth(int u , int k){
	if(tree[u].l==tree[u].r)return tree[u].l;
	int x = tree[tree[u].ls].sum;
	if(k<=x)return query_kth(tree[u].ls,k);
	else return query_kth(tree[u].rs,k-x);
}
int query_x(int i , int l , int r){
    if(l>r)return 0;
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].sum;
	int sum = 0;
	if(tree[tree[i].ls].r>=l)sum += query_x(tree[i].ls,l,r);
	if(tree[tree[i].rs].l<=r)sum += query_x(tree[i].rs,l,r);
	return sum;
}
int get_x(int id , int x){
	return query_x(rt[id],1,x-1);
}
int get_minx(int id , int x){
	int nth = get_x(id,x);
	return query_kth(rt[id],nth);
}
int get_maxx(int id , int x){
	int nth = get_x(id,x);
	return query_kth(rt[id],nth+1);
}

无源汇上下界可行流的建图部分

点击查看代码
for(int i=1;i<=m;i++){
	int u , v , r;cin >> u >> v >> l[i] >> r;
	add_edge(u,v,r-l[i]);
	id[i] = cnt , d[u] -= l[i] , d[v] += l[i];
}
int sum = 0;
for(int i=1;i<=n;i++){
	if(d[i]>0){
		add_edge(s,i,d[i]);
		sum += d[i];
	}else if(d[i]<0){
		add_edge(i,t,-d[i]);
	}
}
int ans = dinic();
if(ans<sum){
	cout << "No";
	return 0;
}
cout << "Yes\n";
for(int i=1;i<=m;i++)cout << flow[id[i]^1] + l[i] << "\n";

矩阵快速幂

点击查看代码
struct node{
	int n , m , a[105][105];
	node operator * (const node &b)const{
		node re;re.n = n , re.m = b.m;
		for(int i=1;i<=re.n;i++){
			for(int j=1;j<=re.m;j++){
				re.a[i][j] = 0;
				for(int k=1;k<=m;k++)re.a[i][j] += a[i][k] * b.a[k][j] , re.a[i][j] %= mod;
			}
		}
		return re;
	}
}a , b;
int k;
node qpow(node x , int y){
	node ans;
	ans.n = x.n , ans.m = x.m;
	for(int i=1;i<=ans.n;i++){
		for(int j=1;j<=ans.m;j++)ans.a[i][j] = (i == j);
	}
	for(;y;y>>=1,x=x*x){
		if(y&1)ans = ans * x;
	}
	return ans;
}

线段树合并与分裂

点击查看代码
struct segtree{
	int l , r , ls , rs , num;
};
vector<segtree> tree;
segtree push_up(int i){
	segtree s = {tree[i].l,tree[i].r,tree[i].ls,tree[i].rs,0};
	if(tree[i].ls)s.num += tree[tree[i].ls].num;
	if(tree[i].rs)s.num += tree[tree[i].rs].num;
	return s;
}
int build(int l , int r){
	tree.push_back({l,r,0,0,0});
	int i = tree.size() - 1;
	if(l==r){
		tree[i].num = a[l];
		return i;
	}
	int mid = (l + r) >> 1;
	tree[i].ls = build(l,mid) , tree[i].rs = build(mid+1,r);
	tree[i] = push_up(i);
	return i;
}
//区间加 
void update(int i , int x , int k){
	if(tree[i].l==tree[i].r){
		tree[i].num += k;
		return;
	}
	int mid = (tree[i].l + tree[i].r) >> 1;
	if(mid>=x){
		if(!tree[i].ls){
			tree.push_back({tree[i].l,mid,0,0,0});
			tree[i].ls = tree.size() - 1;
		}
		update(tree[i].ls,x,k);
	}else{
		if(!tree[i].rs){
			tree.push_back({mid+1,tree[i].r,0,0,0});
			tree[i].rs = tree.size() - 1;
		}
		update(tree[i].rs,x,k);
	}
	tree[i] = push_up(i);
}
//合并 
int merge(int i1 , int i2){
	if(!i1)return i2;
	if(!i2)return i1;
	if(tree[i1].l==tree[i1].r){
		tree[i1].num += tree[i2].num;
		return i1;
	}
	tree[i1].ls = merge(tree[i1].ls,tree[i2].ls);
	tree[i1].rs = merge(tree[i1].rs,tree[i2].rs);
	tree[i1] = push_up(i1);
	return i1;
}
//分裂出[x,y] 
void split(int &p , int &q , int x , int y){
	if(!p||x>tree[p].r||y<tree[p].l)return;
	if(x<=tree[p].l&&y>=tree[p].r){
		q = p , p = 0;
		return;
	}
	if(!q){
		tree.push_back({tree[p].l,tree[p].r,0,0,0});
		q = tree.size() - 1; 
	}
	int mid = (tree[p].l + tree[p].r) >> 1;
	if(tree[p].ls)split(tree[p].ls,tree[q].ls,x,y);
	if(tree[p].rs)split(tree[p].rs,tree[q].rs,x,y);
	tree[p] = push_up(p) , tree[q] = push_up(q); 
}
int query(int i , int l , int r){
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].num;
	int sum = 0;
	if(tree[i].ls&&tree[tree[i].ls].r>=l)sum += query(tree[i].ls,l,r);
	if(tree[i].rs&&tree[tree[i].rs].l<=r)sum += query(tree[i].rs,l,r);
	return sum;
}
int get_kth(int i , int k){
	if(tree[i].l==tree[i].r)return tree[i].l;
	if(k<=tree[tree[i].ls].num)return get_kth(tree[i].ls,k);
	else if(k<=tree[i].num)return get_kth(tree[i].rs,k-tree[tree[i].ls].num);
	else return -1; 
}
posted @ 2026-07-14 14:39  虚空远行者  阅读(7)  评论(0)    收藏  举报