Petrozavodsk Summer 2024. Day 1. Welcome Contest

Preface

整个国庆就训两天,摆烂这一块

这场感觉前期题里计数偏多,只能说毛子场是这样的;然后有人写 D 的时候猪脑过载,占了 90 min 机时导致队友早就会了的 B 没时间写,我不说是谁


A. Adding Integers

把组合式子拆开发现对原序列求差分 \(d_i=a_i-a_{i-1}\) 后,组合意义为:把 \(n\) 个球放到 \(q+1\) 个盒子里,其中第 \(i\) 个盒子里放 \(d_i\) 个球

对所有的 \(\{d\}\) 形态求和后就是 \(n\) 个带标号球放 \(q+1\) 个带标号盒子,方案数为 \((q+1)^n\),数据范围允许暴力快速幂通过

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int mod=998244353;
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
int main()
{
    int t,n,k;
    for (scanf("%d",&t);t;--t)
    {
        scanf("%d%d",&n,&k);
        int ans=0;
        for (RI i=1;i<=k;++i)
        (ans+=quick_pow(i+1,n))%=mod;
        printf("%d\n",ans);
    }
    return 0;
}

B. Bottles

把所有东西都看成有标号的,然后考虑枚举第一次喝解药的位置 \(fir\)

首先把剩下的 \(e-1\) 解药填入后面 \(e+p+w-fir\) 个位置里,然后考虑从发作时间短的毒药开始考虑

\(pos=\max(0,fir-t-1)\),则每个会致死的毒药都恰有 \(e+p+w-e-pos=p+w-pos\) 种选法

对于剩下的毒药和水,放哪里都无所谓,贡献自然很好维护

#include<cstdio>
#include<iostream>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
const int N=300005,mod=998244353;
int e,p,w,t,fact[N],ifac[N];
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void init(CI n)
{
    fact[0]=1;
    for (RI i=1;i<=n;++i) fact[i]=1LL*fact[i-1]*i%mod;
    ifac[n]=quick_pow(fact[n]);
    for (RI i=n-1;i>=0;--i) ifac[i]=1LL*ifac[i+1]*(i+1)%mod;
}
inline int C(CI n,CI m)
{
    if (n<0||m<0||n<m) return 0;
    return 1LL*fact[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int main()
{
    scanf("%d%d%d%d",&e,&p,&w,&t);
    init(e+p+w); int ans=0;
    for (RI fir=1;fir<=e+p+w;++fir)
    {
        int cur=1LL*e*C(e+p+w-fir,e-1)%mod*fact[e-1]%mod;
        int pos=max(0,fir-t-1);
        cur=1LL*cur*quick_pow(max(0,p+w-pos),min(pos,p))%mod;
        cur=1LL*cur*C(p+w-pos,max(0,p-pos))%mod*fact[max(0,p-pos)]%mod;
        cur=1LL*cur*fact[w]%mod;
        (ans+=cur)%=mod;
    }
    return printf("%d",1LL*ans*ifac[e+p+w]%mod),0;
}

C. Counting Orthogonal Pairs

队友开局推的

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

LL solve() {
    int x; cin >> x;
    if (x % 2 == 1) return 0;
    else return 1LL* (x/2-1) * x;
}

signed main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int t; cin >> t; while (t--) cout << solve() << '\n';
    return 0;
}

D. Divine Tree

随便选一个点当根,考虑最后如果是把所有的 G 扔到子树 \(x\) 里(移动 B 进去的方案同理)

这个代价等价于把 \(x\) 子树里所有 B 移动到点 \(x\) 的距离和,再加上把子树 \(x\) 外部的所有 B 移动到 \(x\) 的距离和

由于修改不改变每个点的信息,因此答案只能在一部分点出取得,可以预处理出这些位置

考虑对一条边 \(x\to y\) 的修改会影响三部分的答案,这个需要画图手动推导一下

最终要实现的就是子树加,树上路径加,以及抛出掉上述两种情况的部分再整体加

写题解的时候想到一个好的实现方法时先全局加上第三种情况的值,然后前两种情况的增量减去第三种情况的增量即可

但当时实现的时候没管那么多了,直接暴力把拆分出的区间(个数是 \(\log\) 级别的)拎出来把中间的补暴力跑一遍修改,复杂度也没啥区别

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<assert.h>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=100005,INF=1e18;
int n,a[N],anc[N],u[N],v[N],w[N],key[N],seq[N],q,e[N],d[N],ans[N];
char s[N]; vector <int> E[N];
class Segment_Tree
{
    private:
        int mn[N<<2],tag[N<<2];
        inline void apply(CI now,CI mv)
        {
            mn[now]+=mv; tag[now]+=mv;
        }
        inline void pushup(CI now)
        {
            mn[now]=min(mn[now<<1],mn[now<<1|1]);
        }
        inline void pushdown(CI now)
        {
            if (tag[now]) apply(now<<1,tag[now]),apply(now<<1|1,tag[now]),tag[now]=0;
        }
    public:
        #define TN CI now=1,CI l=1,CI r=n
        #define LS now<<1,l,mid
        #define RS now<<1|1,mid+1,r
        inline void build(TN)
        {
            tag[now]=0; if (l==r) return (void)(mn[now]=(key[seq[l]]?0:INF));
            int mid=l+r>>1; build(LS); build(RS); pushup(now);
        }
        inline void modify(CI beg,CI end,CI mv,TN)
        {
            if (beg<=l&&r<=end) return apply(now,mv);
            int mid=l+r>>1; pushdown(now);
            if (beg<=mid) modify(beg,end,mv,LS);
            if (end>mid) modify(beg,end,mv,RS);
            pushup(now);
        }
        inline int query(void)
        {
            return mn[1];
        }
        #undef TN
        #undef LS
        #undef RS
}SEG;
vector <pair <int,int>> itv;
namespace Heavy_Division
{
    int dep[N],dfn[N],top[N],idx,sz[N],son[N];
    inline void DFS1(CI now=1,CI fa=0)
    {
        sz[now]=1; dep[now]=dep[fa]+1; anc[now]=fa;
        for (auto to:E[now])
        {
            if (to==fa) continue;
            DFS1(to,now); sz[now]+=sz[to];
            if (sz[to]>sz[son[now]]) son[now]=to;
        }
    }
    inline void DFS2(CI now=1,CI tf=1)
    {
        seq[dfn[now]=++idx]=now; top[now]=tf;
        if (son[now]) DFS2(son[now],tf);
        for (auto to:E[now])
        {
            if (to==anc[now]||to==son[now]) continue;
            DFS2(to,to);
        }
    }
    inline void modify_path(int x,CI mv)
    {
        // printf("x = %lld\n",x);
        while (top[x]!=top[1])
        {
            itv.emplace_back(dfn[top[x]],dfn[x]);
            // printf("(%lld, %lld) + %lld\n",dfn[top[x]],dfn[x],mv);
            SEG.modify(dfn[top[x]],dfn[x],mv);
            x=anc[top[x]];
        }
        // printf("(%lld, %lld) + %lld\n",dfn[1],dfn[x],mv);
        itv.emplace_back(dfn[1],dfn[x]);
        SEG.modify(dfn[1],dfn[x],mv);
    }
    inline void modify_sbt(CI x,CI mv)
    {
        itv.emplace_back(dfn[x],dfn[x]+sz[x]-1);
        SEG.modify(dfn[x],dfn[x]+sz[x]-1,mv);
    }
};
using namespace Heavy_Division;
int szb[N],szg[N];
inline void DFS3(CI G,CI now=1,CI fa=0)
{
    szg[now]=szb[now]=0;
    if (a[now]) ++szg[now]; else ++szb[now];
    for (auto to:E[now])
    {
        if (to==fa) continue;
        DFS3(G,to,now);
        szg[now]+=szg[to];
        szb[now]+=szb[to];
    }
}
inline void solve(CI G)
{
    for (RI i=1;i<=n;++i)
    key[i]=(sz[i]==G);
    DFS3(G); SEG.build();
    // printf("key: ");
    // for (RI i=1;i<=n;++i)
    // if (key[i]) printf("%d ",i);
    // putchar('\n');
    auto update=[&](CI x,CI y,CI d)
    {
        itv.clear();
        modify_path(x,szb[y]*d);
        modify_sbt(y,(G-szg[y])*d);
        sort(itv.begin(),itv.end());
        for (RI i=0;i+1<(int)itv.size();++i)
        assert(itv[i].second<=itv[i+1].first);
        int lst=1;
        for (auto [l,r]:itv)
        {
            assert(l<=r);
            if (lst<=l-1)
            {
                // printf("(%lld, %lld) + %lld\n",lst,l-1,szg[y]*d);
                SEG.modify(lst,l-1,szg[y]*d);
            }
            lst=r+1;
        }
        if (lst<=n) SEG.modify(lst,n,szg[y]*d);
    };
    for (RI i=1;i<n;++i)
    {
        int x=u[i],y=v[i];
        if (dep[x]>dep[y]) swap(x,y);
        // printf("x = %lld, y = %lld, d = %lld\n",x,y,d[i]);
        update(x,y,w[i]);
    }
    for (RI i=1;i<=q;++i)
    {
        int x=u[e[i]],y=v[e[i]];
        if (dep[x]>dep[y]) swap(x,y);
        // printf("x = %lld, y = %lld, d = %lld\n",x,y,d[i]);
        update(x,y,d[i]);
        ans[i]=min(ans[i],SEG.query());
    }
}
signed main()
{
    scanf("%lld%s",&n,s+1);
    int G=0,B=0;
    for (RI i=1;i<=n;++i)
    if (s[i]=='G') ++G; else ++B;
    for (RI i=1;i<n;++i)
    {
        scanf("%lld%lld%lld",&u[i],&v[i],&w[i]);
        E[u[i]].emplace_back(v[i]);
        E[v[i]].emplace_back(u[i]);
    }
    scanf("%lld",&q);
    for (RI i=1;i<=q;++i)
    scanf("%lld%lld",&e[i],&d[i]),ans[i]=INF;
    DFS1(); DFS2();
    for (RI i=1;i<=n;++i) a[i]=(s[i]=='G');
    solve(G);
    for (RI i=1;i<=n;++i) a[i]=(s[i]=='B');
    solve(B);
    for (RI i=1;i<=q;++i) printf("%lld\n",ans[i]);
    return 0;
}

E. Experiments With Divine Trees

这个题队友好像也会了,同样没时间写;感觉这场我的博弈和 DS 出的慢要背大锅啊


H. Heroes and Illusions

这题纯队友讨论出来的,我也不知道做法

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

const int N = 1e5+5;
const int MOD = 998244353;

void mul(int &x, int a) { x=1LL*x*a%MOD; }
LL sqr(int x) {return 1LL*x*x;}

int n, fac[N], invf[N];
LL k;

int powe(int x, int p) {
    int res = 1;
    while (p>0) {if (p&1) mul(res, x); mul(x, x); p>>=1;}
    return res;
}

int inv(int x) {return powe(x, MOD-2);}

int C(int n, int m) {
    return 1LL*fac[n]*invf[m]%MOD*invf[n-m]%MOD;
}

int solve() {
    cin >> n >> k;
    if (0 == k) return 1;
    if (1LL*(n+1)*(n+1) < 4*k) return 0;
    LL det = sqr(n+1)-4*k;
    if (sqr(int(sqrtl(det))) != det) return 0;
    det = int(sqrtl(det));
    if (n+1 < det || (n+1-det)%2 != 0) return 0;
    int i = (n+1-det)/2;
    
    if (i == k/i) return C(n, i)%MOD;
    else return (C(n, i) + C(n, k/i))%MOD;
    return 0;
}

signed main() {
    ios::sync_with_stdio(0); cin.tie(0);
    fac[0] = fac[1] = invf[0] = invf[1] = 1;
    for (int i=2; i<N; ++i) fac[i] = 1LL*fac[i-1]*i%MOD;
    invf[N-1] = inv(fac[N-1]);
    for (int i=N-1; i>1; --i) invf[i-1] = 1LL*invf[i]*i%MOD;
    int T; cin >> T; while (T--) cout << solve() << '\n';
    return 0;
}

J. Jumping Game

首先根据经典的图上博弈模型,考虑将图黑白染色并把能走到的点连边

先手必败的条件等价去掉起始点时剩下的图有完美匹配

不难发现当 \(r,c\) 都比较大时,偶数个点一定先手必胜(因为剩下点个数为奇数),奇数个点时也可以认为剩下部分能完美匹配

但是 \(r,c\) 较小的时候就是会有需要讨论的 Corner Case,然后我们只需要暴力打个表找出这些情况即可,\(\min(r,c)\le 2\) 的情况是 trivial 的

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int t,r,c,a,b;
int main()
{
    for (scanf("%d",&t);t;--t)
    {
        scanf("%d%d%d%d",&r,&c,&a,&b);
        if (r>c) swap(r,c),swap(a,b);
        if (r==1) { puts("Brahma"); continue; }
        if (r==2)
        {
            int left=(b-1)/2,right=(c-b)/2;
            if (left%2==1||right%2==1) puts("Annapurna");
            else puts("Brahma");
            continue;
        }
        if (r==3&&c==3)
        {
            puts(a==2&&b==2?"Brahma":"Annapurna");
            continue;
        }
        if (r==3&&c==5)
        {
            if ((a+b)%2==1) { puts("Annapurna"); continue; }
            if ((a==1&&b==3)||(a==3&&b==3)) puts("Annapurna");
            else puts("Brahma");
            continue;
        }
        if (r%2==0||c%2==0) puts("Annapurna");
        else puts((a+b)%2==0?"Brahma":"Annapurna");
    }
    return 0;
}

K. Kangaroo On Graph

由于图是个 DAG,因此可以拓扑排序求最短路

对于每个点 \(x\),把所有能到达它的路径权值 \(val\) 和前驱点 \(pre\) 看作二元组并排序存下来

对于其所有出边我们暴力在里面找个最优的更新即可,分析一波复杂度是线性的

#include<cstdio>
#include<iostream>
#include<set>
#include<vector>
#include<queue>
#include<array>
#include<algorithm>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=200005,INF=1e18;
typedef pair <int,int> pi;
int n,m,k,deg[N]; vector <pi> f[N];
vector <pi> v[N]; set <array <int,3>> ban;
signed main()
{
    scanf("%lld%lld",&n,&m);
    for (RI i=1;i<=m;++i)
    {
        int x,y,z;
        scanf("%lld%lld%lld",&x,&y,&z);
        v[x].push_back({y,z}); ++deg[y];
    }
    scanf("%lld",&k);
    for (RI i=1;i<=k;++i)
    {
        int a,b,c;
        scanf("%lld%lld%lld",&a,&b,&c);
        ban.insert({a,b,c});
    }
    queue <int> q; f[1].push_back({0,0});
    for (RI i=1;i<=n;++i) if (deg[i]==0) q.push(i);
    while (!q.empty())
    {
        int now=q.front(); q.pop();
        sort(f[now].begin(),f[now].end());
        for (auto [to,w]:v[now])
        {
            int val=INF;
            for (auto [dis,lst]:f[now])
            {
                if (ban.count({lst,now,to})) continue;
                val=dis; break;
            }
            if (val!=INF) f[to].push_back({val+w,now});
            if (--deg[to]==0) q.push(to);
        }
    }
    if (f[n].empty()||f[n][0].first>=INF) puts("-1"); else printf("%lld",f[n][0].first);
    return 0;
}

L. Low Cost Set

首先不难发现把所有的区间都扔到集合里一定是个合法解

考虑如果存在两个区间 \([a,b),[c,d)\),满足 \(a<c<b<d\)(即它们有交),那么我们可以把它们拆成 \([a,c),[c,b),[b,d)\),以此减少 \([b,c)\) 的贡献

不难发现由于拆分只能进行一次,因此两个区间配对拆分后就不能再进行操作了

把能配对拆分的区间之间连对应权值的边,转化为一般图的最大权匹配,然后去 UOJ 上抄个老哥的板子跑一跑就行

#include<bits/stdc++.h>
using namespace std;
#define all(x) (x).begin(),(x).end()
namespace weighted_blossom_tree
{
	#define d(x) (lab[x.u]+lab[x.v]-e[x.u][x.v].w*2)
	const int N=105*2;//两倍点数
	typedef long long ll;//总和大小
	typedef ll T;//权值大小
	//均不允许无符号
	const T inf=numeric_limits<int>::max()>>1;
	struct Q
	{
		int u,v;
		T w;
	} e[N][N];
	T lab[N];
	int n,m=0,id,h,t,lk[N],sl[N],st[N],f[N],b[N][N],s[N],ed[N],q[N];
	vector<int> p[N];
	void upd(int u,int v) {if (!sl[v]||d(e[u][v])<d(e[sl[v]][v])) sl[v]=u;}
	void ss(int v)
	{
		sl[v]=0;
		for (int u=1;u<=n;u++) if (e[u][v].w>0&&st[u]!=v&&!s[st[u]]) upd(u,v);
	}
	void ins(int u) {if (u<=n) q[++t]=u; else for (int v:p[u]) ins(v);}
	void mdf(int u,int w)
	{
		st[u]=w;
		if (u>n) for (int v:p[u]) mdf(v,w);
	}
	int gr(int u,int v)
	{
		if ((v=find(all(p[u]),v)-p[u].begin())&1)
		{
			reverse(1+all(p[u]));
			return (int)p[u].size()-v;
		}
		return v;
	}
	void stm(int u,int v)
	{
		lk[u]=e[u][v].v;
		if (u<=n) return;
		Q w=e[u][v];
		int x=b[u][w.u],y=gr(u,x),i;
		for (i=0;i<y;i++) stm(p[u][i],p[u][i^1]);
		stm(x,v);
		rotate(p[u].begin(),y+all(p[u]));
	}
	void aug(int u,int v)
	{
		int w=st[lk[u]];
		stm(u,v);
		if (!w) return;
		stm(w,st[f[w]]);
		aug(st[f[w]],w);
	}
	int lca(int u,int v)
	{
		for (++id;u|v;swap(u,v))
		{
			if (!u) continue;
			if (ed[u]==id) return u;
			ed[u]=id;//??????????v?? 这是原作者的注释,我也不知道是啥
			if (u=st[lk[u]]) u=st[f[u]];
		}
		return 0;
	}
	void add(int u,int a,int v)
	{
		int x=n+1,i,j;
		while (x<=m&&st[x]) ++x;
		if (x>m) ++m;
		lab[x]=s[x]=st[x]=0;lk[x]=lk[a];
		p[x].clear();p[x].push_back(a);
		for (i=u;i!=a;i=st[f[j]]) p[x].push_back(i),p[x].push_back(j=st[lk[i]]),ins(j);//复制,改一处
		reverse(1+all(p[x]));
		for (i=v;i!=a;i=st[f[j]]) p[x].push_back(i),p[x].push_back(j=st[lk[i]]),ins(j);
		mdf(x,x);
		for (i=1;i<=m;i++) e[x][i].w=e[i][x].w=0;
		memset(b[x]+1,0,n*sizeof b[0][0]);
		for (int u:p[x])
		{
			for (v=1;v<=m;v++) if (!e[x][v].w||d(e[u][v])<d(e[x][v])) e[x][v]=e[u][v],e[v][x]=e[v][u];
			for (v=1;v<=n;v++) if (b[u][v]) b[x][v]=u;
		}
		ss(x);
	}
	void ex(int u)  // s[u] == 1
	{
		for (int x:p[u]) mdf(x,x);
		int a=b[u][e[u][f[u]].u],r=gr(u,a),i;
		for (i=0;i<r;i+=2)
		{
			int x=p[u][i],y=p[u][i+1];
			f[x]=e[y][x].u;
			s[x]=1;s[y]=0;
			sl[x]=0;ss(y);
			ins(y);
		}
		s[a]=1;f[a]=f[u];
		for (i=r+1;i<p[u].size();i++) s[p[u][i]]=-1,ss(p[u][i]);
		st[u]=0;
	}
	bool on(const Q &e)
	{
		int u=st[e.u],v=st[e.v],a;
		if(s[v]==-1)
		{
			f[v]=e.u;s[v]=1;
			a=st[lk[v]];
			sl[v]=sl[a]=s[a]=0;
			ins(a);
		}
		else if(!s[v])
		{
			a=lca(u,v);
			if (!a) return aug(u,v),aug(v,u),1;
			else add(u,a,v);
		}
		return 0;
	}
	bool bfs()
	{
		memset(s+1,-1,m*sizeof s[0]);
		memset(sl+1,0,m*sizeof sl[0]);
		h=1;t=0;
		int i,j;
		for (i=1;i<=m;i++) if (st[i]==i&&!lk[i]) f[i]=s[i]=0,ins(i);
		if (h>t) return 0;
		while (1)
		{
			while (h<=t)
			{
				int u=q[h++],v;
				if (s[st[u]]!=1) for (v=1; v<=n;v++) if (e[u][v].w>0&&st[u]!=st[v])
				{
					if (d(e[u][v])) upd(u,st[v]); else if (on(e[u][v])) return 1;
				}
			}
			T x=inf;
			for (i=n+1;i<=m;i++) if (st[i]==i&&s[i]==1) x=min(x,lab[i]>>1);
			for (i=1;i<=m;i++) if (st[i]==i&&sl[i]&&s[i]!=1) x=min(x,d(e[sl[i]][i])>>s[i]+1);
			for (i=1;i<=n;i++) if (~s[st[i]]) if ((lab[i]+=(s[st[i]]*2-1)*x)<=0) return 0;
			for (i=n+1;i<=m;i++) if (st[i]==i&&~s[st[i]]) lab[i]+=(2-s[st[i]]*4)*x;
			h=1;t=0;
			for (i=1;i<=m;i++) if (st[i]==i&&sl[i]&&st[sl[i]]!=i&&!d(e[sl[i]][i])&&on(e[sl[i]][i])) return 1;
			for (i=n+1;i<=m;i++) if (st[i]==i&&s[i]==1&&!lab[i]) ex(i);
		}
		return 0;
	}
	template<typename TT> ll max_weighted_general_match(int N,const vector<tuple<int,int,TT>> &edges)//[1,n],返回权值
	{
		memset(ed+1,0,m*sizeof ed[0]);
		memset(lk+1,0,m*sizeof lk[0]);
		n=m=N;id=0;
		iota(st+1,st+n+1,1);
		int i,j;
		T wm=0;
		ll r=0;
		for (i=1;i<=n;i++) for (j=1;j<=n;j++) e[i][j]={i,j,0};
		for (auto [u,v,w]:edges) wm=max(wm,e[v][u].w=e[u][v].w=max(e[u][v].w,(T)w));
		for (i=1;i<=n;i++) p[i].clear();
		for (i=1;i<=n;i++) for (j=1;j<=n;j++) b[i][j]=i*(i==j);
		fill_n(lab+1,n,wm);
		while (bfs());
		for (i=1;i<=n;i++) if (lk[i]) r+=e[i][lk[i]].w;
		return r/2;
	}
	#undef d
}
using weighted_blossom_tree::max_weighted_general_match,weighted_blossom_tree::lk;
#define RI register int
const int N=105;
int k,l[N],r[N],A[N<<1];
int main()
{
    scanf("%d",&k);
    for (RI i=1;i<=k;++i)
    scanf("%d%d",&l[i],&r[i]);
    for (RI i=1;i<2*k;++i)
    scanf("%d",&A[i]);
    long long ans=0;
    for (RI i=1;i<=k;++i)
    for (RI j=l[i];j<r[i];++j) ans+=A[j];
	vector<tuple<int,int,long long>> edges;
    for (RI i=1;i<=k;++i)
    for (RI j=1;j<=k;++j)
    {
        if (i==j) continue;
        int a=l[i],b=r[i],c=l[j],d=r[j];
        if (a<c&&c<b&&b<d)
        {
            long long sum=0;
            for (RI s=c;s<b;++s) sum+=A[s];
            edges.emplace_back(i,j,sum);
        }
    }
    printf("%lld",ans-max_weighted_general_match(k,edges));
    return 0;
}

Postscript

争取 Regional 前保持一周两训吧,能做到吗(还剩两次!)

posted @ 2025-10-07 23:48  空気力学の詩  阅读(5)  评论(0)    收藏  举报