社区讨论

求改(信息队勿入)不要题解 必关

B3851[GESP202306 四级] 图像压缩参与者 4已保存回复 6

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
6 条
当前快照
1 份
快照标识符
@m3x2azun
此快照首次捕获于
2024/11/25 21:26
去年
此快照最后确认于
2025/11/04 13:55
4 个月前
查看原帖
CPP
// https://www.luogu.com.cn/problem/B3851
#include<bits/stdc++.h>
using namespace std;

//  将一行字符串以2位为单位拆分成多个子字符串
vector<string> splite(string s) {
    vector<string> res;
    for(int i=0; i<s.size()/2; i++) {
        string tmp = s.substr(2*i,2);
        res.push_back(tmp);
    }
    return res;
}

// 计数器
map<string, int> counter;
void counting(vector<string> ss) {
    for(auto s : ss) {
        counter[s]++;
    }
}

// 排序规则
bool order_rule(pair<string, int> p1, pair<string, int> p2) {
    if(p1.second>p2.second) {
        return true;
    }
    else if(p1.second<p2.second) {
        return false;
    }
    else {
        if(p1.first<p2.first) {
            return true;
        }
        else {
            return false;
        }
    }
}
// 用来排序的临时存储
vector<pair<string, int>> counter_pairs;

// 把16进制转10进制
int c16to10(char x) {
    return (x <= '9' ? x - '0' : x - 'A' + 10);
}
// 16进制减法(返回值为10进制)
int minus16(string a, string b) {
    int a10 = c16to10(a[0]) * 16 + c16to10(a[1]);
    int b10 = c16to10(b[0]) * 16 + c16to10(b[1]);
    return a10-b10;
}
// 只存前16名
map<string, char> ziped16;
// 存所有的
map<string, char> ziped;
// 计算每个颜色对应的压缩后的颜色是什么
void ziping() {
    for(int i=0; i<16; i++) {
        string ziped_key = counter_pairs[i].first;
        ziped[ziped_key] =  (i<=9 ? '0'+i : 'A'+i-10);
        ziped16[ziped_key] =  (i<=9 ? '0'+i : 'A'+i-10);
    }

    for(int i=16; i<counter_pairs.size(); i++) {
        string ziped_key = counter_pairs[i].first;
        // 在ziped16中,二分查找到比ziped_key相等或大的第一个位置
        auto pos = ziped16.lower_bound(ziped_key);
        // 没有更大的
        if(pos == ziped16.end()) {
            pos--;
            ziped[ziped_key] = pos->second;
        }
        // 没有更小的
        else if(pos == ziped16.begin()) {
            ziped[ziped_key] = pos->second;
        }
        else{
            string greater_key = pos->first;
            pos--;
            string less_key = pos->first;
            if(minus16(greater_key, ziped_key) < minus16(ziped_key, less_key)) {
                ziped[ziped_key] = ziped[greater_key];
            } 
            else if(minus16(greater_key, ziped_key) > minus16(ziped_key, less_key)) {
                ziped[ziped_key] = ziped[less_key];
            }
            else {
                ziped[ziped_key] = ziped[min(greater_key, less_key)];
            }
        }
    }
}

int n;
vector<string> dt; // 缓存题目输入,用于最后的输出
int main() {
    cin >> n;
    while(n--) {
        string s;
        cin >> s;
        dt.push_back(s);
        vector<string> tt = splite(s);
        counting(tt);
    }
    for(auto s : counter) {
        counter_pairs.push_back(s);
    }
    sort(counter_pairs.begin(), counter_pairs.end(), order_rule);
    // 题目要求的一行输出
    for(int i=0; i<16; i++) {
        cout << counter_pairs[i].first;
    }
    cout << endl;

    ziping();
    for(auto s : dt) {
        vector<string> tt = splite(s);
        for(auto ss : tt) {
            cout << ziped[ss];
        }
        cout << endl;  
    }
    return 0;
}

回复

6 条回复,欢迎继续交流。

正在加载回复...