ABC416D

问题简化

转化为由\(A, B\) 中的元素组成的二元组,使得两个元素的和取模 \(m\) 的和最小

Slove

贪心的,先尽可能的组成更多的二元组使得二元组亮相的和为 \(m\)

readf(&n), readf(&m);
ll cntA = 0, cntB = 0, ans = 0;
std::multiset<ll> a, b, c;
for (size_t i = 1; i <= n; i++) {
    ll val = readf<ll>();
    a.insert(val);
    c.insert(m - val);
}

//现在的s
for (size_t i = 1; i <= n; i++) {
    ll val;
    readf(&val);
    if (c.count(val)) {
        a.erase(a.find(m - val));
        c.erase(val);
    }
    else {
        b.insert(val);
    }
}

对于剩下的元素,希望二元组的和取模 \(m\) 尽可能的小

贪心的,先把较大的解决掉, 比较大的比小的更麻烦。

从 $A, B $ 中取一个最大值

对于最大值由2中解决方式

  • 让其加上一个值,使得和超过\(m\), 取模让其变小

  • 让其加上一个值,使得和尽量小

#define _FREAD        true
#define MAX_INF       1e18
#define MAX_NUM_SIZE  35
#define MAXN          (size_t)(3e5+5)

typedef long long int ll;
typedef unsigned long long int ull;

//快读函数声明
template< typename Type >
inline Type readf(Type* p = nullptr);

//快速输出函数
template<typename Type>
inline void writef(Type x);

ll arrA[MAXN], arrB[MAXN];
ll t, n, m;

inline void slove() {
    readf(&n), readf(&m);
    ll cntA = 0, cntB = 0, ans = 0;
    std::multiset<ll> a, b, c;
    for (size_t i = 1; i <= n; i++) {
        ll val = readf<ll>();
        a.insert(val);
        c.insert(m - val);
    }

    //现在的s
    for (size_t i = 1; i <= n; i++) {
        ll val;
        readf(&val);
        if (c.count(val)) {
            a.erase(a.find(m - val));
            c.erase(val);
        }
        else {
            b.insert(val);
        }
    }
    

    ll apos = cntA, bpos = cntB;
    while (!a.empty()) {
        std::multiset<ll>::iterator aend = a.end(), bend = b.end();
        --aend, --bend;
        if ((*aend) > (*bend)) {
            //现在a最大的大于b最大
            ll val = m - *(aend), temp = 0;
            std::multiset<ll>::iterator p = b.lower_bound(val);
            if (p == b.end()) {
                temp += *b.begin();
                b.erase(b.begin());
            }
            else {
                if ((*p + *aend) % m < (*b.begin() + *(aend)) % m) {
                    temp += *p;
                    b.erase(p);
                }
                else {
                    temp += *b.begin();
                    b.erase(b.begin());
                }
            }
            temp += *(aend);
            temp %= m;
            ans += temp;
            a.erase(aend);
        }
        else {
            //现在a最大的大于b最大
            ll val = m - *(bend), temp = 0;
            std::multiset<ll>::iterator p = a.lower_bound(val);
            if (p == a.end()) {
                temp += *a.begin();
                a.erase(a.begin());
            }
            else {
                if ((*p + *(bend)) % m < (*a.begin() + *(bend)) % m) {
                    temp += *p;
                    a.erase(p);
                }
                else {
                    temp += *a.begin();
                    a.erase(a.begin());
                }
            }
            temp += *(bend);
            temp %= m;
            ans += temp;
            b.erase(bend);
        }
    }

    
    printf("%lld\n", ans);
    return;
}

int main() {

#ifdef _FREOPEN
    freopen("input.txt", "r", stdin);
#endif // _FREOPEN

#ifdef _RUN_TIME
    clock_t start = clock();
#endif // _RUN_TIME

	readf(&t);

    while (t--) {
		slove();
    }



#ifdef _RUN_TIME
    printf("The running duration is not less than %ld ms\n", clock() - start);
#endif // _RUN_TIME
    return 0;
}


posted @ 2025-08-24 22:59  txp2025  阅读(15)  评论(0)    收藏  举报