第35次CCF計算機軟件能力認證-5-木板切割

?原題鏈接:

TUOJ

我自己寫的35分正確但嚴重超時的代碼

#include <bits/stdc++.h>
using namespace std;
int main()
{int n, m, k;cin >> n >> m >> k;vector<unordered_map<int, int>> mp(2);int y;for (int i = 1; i <= n; i++){cin >> y;mp[1][i] = y;}while (k--){int x, l, r;cin >> x >> l >> r;unordered_map<int, int> tmp;int color_num = 0, num = 0;unordered_set<int> color_type;int pos = -1;for (int i = l; i <= r; i++){if (mp[x].count(i)){int color = mp[x][i];tmp[i] = color;color_type.insert(color);if (pos == -1 || tmp[i] != tmp[pos])num++;pos = i;mp[x].erase(i);}}color_num = color_type.size();mp.push_back(tmp);cout << color_num << ' ' << num << endl;}
}

過了7個樣例,35分,對于現在的我來說也還行

?

知道你們肯定不滿足35分,特地給出了大佬寫的代碼,300行+,自己寫一個數據結構,我只能說nb,水平有限,不作說明

CCF-CSP第35次認證第五題——木板切割【C++滿分題解;平衡樹set,線段樹,分塊預處理,位圖;區間合并、懶更新與分治、位運算優化】_csp 木板切割-CSDN博客

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <cstdint>
using namespace std;// ------------------------
// 線段樹部分:支持查詢區間內顏色段數、左右端顏色
// ------------------------// 線段樹節點結構
struct SegmentTreeNode {int left, right;        // 節點區間 [left, right]int segment_count;      // 該區間內顏色段數(相鄰顏色相同視為同一段)int left_color, right_color;  // 區間最左/最右的顏色SegmentTreeNode *left_child, *right_child;SegmentTreeNode(int l, int r): left(l), right(r), segment_count(1), left_color(0), right_color(0),left_child(nullptr), right_child(nullptr) {}
};// 建樹:葉節點對應單個位置,其顏色直接取自 colors 數組
SegmentTreeNode* buildTree(const vector<int>& colors, int l, int r) {SegmentTreeNode* node = new SegmentTreeNode(l, r);if (l == r) {node->left_color = node->right_color = colors[l];node->segment_count = 1;return node;}int mid = (l + r) / 2;node->left_child = buildTree(colors, l, mid);node->right_child = buildTree(colors, mid + 1, r);node->left_color = node->left_child->left_color;node->right_color = node->right_child->right_color;// 初步合并左右子區間的段數node->segment_count = node->left_child->segment_count + node->right_child->segment_count;// 如果左右子區間的邊界顏色相同,則合并為一段if (node->left_child->right_color == node->right_child->left_color) {node->segment_count--;}return node;
}// 查詢區間 [l, r] 的顏色段數以及左右端顏色
void query(SegmentTreeNode* node, int l, int r, int& segment_count, int& first_color, int& last_color) {if (node == nullptr || node->right < l || node->left > r) {segment_count = 0;first_color = -1;last_color = -1;return;}if (l <= node->left && node->right <= r) {segment_count = node->segment_count;first_color = node->left_color;last_color = node->right_color;return;}int left_seg = 0, right_seg = 0;int left_first = -1, left_last = -1;int right_first = -1, right_last = -1;query(node->left_child, l, r, left_seg, left_first, left_last);query(node->right_child, l, r, right_seg, right_first, right_last);if (left_seg == 0) {segment_count = right_seg;first_color = right_first;last_color = right_last;} else if (right_seg == 0) {segment_count = left_seg;first_color = left_first;last_color = left_last;} else {segment_count = left_seg + right_seg;if (left_last == right_first) segment_count--;first_color = left_first;last_color = right_last;}
}// ------------------------
// 塊狀分解部分:預處理整個顏色數組以快速回答區間內“不同顏色數”查詢  
// 用 64 位整數數組模擬 bitset,每一位表示某種顏色是否出現。
// ------------------------int B;            // 塊大小(可調)
int numBlocks;    // 總塊數
int W;            // 每個 bitset 需要的 64 位整數數量(W = ceil(m/64))
vector<int> colors;  // 顏色數組(1-indexed)
vector<vector<uint64_t>> blockOR;  // 每塊預處理的“或”結果// 查詢區間 [L,R] 內顏色的 bitset(即各顏色是否出現的標記),返回大小為 W 的 uint64_t 數組
vector<uint64_t> distinctQuery(int L, int R) {vector<uint64_t> res(W, 0ULL);int startBlock = (L - 1) / B;int endBlock = (R - 1) / B;if (startBlock == endBlock) {// 區間完全落在同一塊,直接遍歷求或for (int i = L; i <= R; i++) {int col = colors[i];int idx = col - 1;res[idx / 64] |= (1ULL << (idx % 64));}} else {// 處理起始塊的部分int blockStartEnd = (startBlock + 1) * B;for (int i = L; i <= blockStartEnd; i++) {int col = colors[i];int idx = col - 1;res[idx / 64] |= (1ULL << (idx % 64));}// 處理中間整塊for (int b = startBlock + 1; b < endBlock; b++) {for (int j = 0; j < W; j++) {res[j] |= blockOR[b][j];}}// 處理結束塊的部分int endBlockStart = endBlock * B + 1;for (int i = endBlockStart; i <= R; i++) {int col = colors[i];int idx = col - 1;res[idx / 64] |= (1ULL << (idx % 64));}}return res;
}// 將 src 的 bitset 結果“或”到 dest 上
void unionBitset(vector<uint64_t>& dest, const vector<uint64_t>& src) {for (int i = 0; i < W; i++) {dest[i] |= src[i];}
}// 統計 bitset 中 1 的個數,即不同顏色數
int countBits(const vector<uint64_t>& bs) {int cnt = 0;for (auto x : bs) {cnt += __builtin_popcountll(x);}return cnt;
}// ------------------------
// 主函數
// ------------------------
int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int n, m, k;cin >> n >> m >> k;// colors 數組采用 1-indexed,下標 1~ncolors.resize(n + 1);bool allDistinct = true; // 標記是否所有顏色都不相同(即 c[i] = i 的情況),用于特殊情況優化for (int i = 1; i <= n; i++) {cin >> colors[i];if (colors[i] != i)allDistinct = false;}// 構建線段樹(當 allDistinct 為 true 時,本質上不用查詢區間信息,但為了代碼統一構造)SegmentTreeNode* root = buildTree(colors, 1, n);// ------------------------// 塊狀分解預處理:構造每塊的顏色“或”信息// ------------------------B = 512;  // 塊大小(可根據實際情況調節)numBlocks = (n + B - 1) / B;// 每個 bitset 長度為 W = ceil(m/64)W = (m + 63) / 64;blockOR.assign(numBlocks, vector<uint64_t>(W, 0ULL));for (int b = 0; b < numBlocks; b++) {int L = b * B + 1;int R = min(n, (b + 1) * B);for (int i = L; i <= R; i++) {int col = colors[i];int idx = col - 1;blockOR[b][idx / 64] |= (1ULL << (idx % 64));}}// ------------------------// 每塊木板維護一個 set,記錄當前木板上存在的區間(區間端點均為原數組下標)// 初始時 1 號木板包含整個區間 [1, n]// ------------------------// 用 pair<int, int> 表示一個區間 [first, second]vector<set<pair<int, int>>> boards(k + 2);  // 共 k+1 號木板,編號 1~k+1boards[1].insert({1, n});// 處理 k 次切割操作// 每次輸入 x, l, r 表示對木板 x 的區間 [l, r] 進行切割,// 切下來的部分構成新的木板,輸出:切下部分的不同顏色數 和 顏色段數(合并相鄰顏色相同的段后)for (int op = 1; op <= k; op++) {int x, l, r;cin >> x >> l >> r;set<pair<int, int>>& current = boards[x];// 收集本次切割中,被切下來的區間vector<pair<int, int>> cut_segments;// 在當前木板的區間集合中找到所有與 [l, r] 有交集的區間auto it = current.lower_bound({l, 0});if (it != current.begin()) --it;while (it != current.end()) {int s = it->first, e = it->second;if (s > r) break;  // 后面的區間起點超過 r,無需繼續if (e < l) { // 當前區間完全在 [l, r] 之前++it;continue;}// 求交集int a = max(s, l), b = min(e, r);if (a <= b) {cut_segments.push_back({a, b});// 從當前木板中移除該區間,并將剩余部分(若有)重新加入auto temp = it;++it;current.erase(temp);if (s < a) {current.insert({s, a - 1});}if (b < e) {current.insert({b + 1, e});}} else {++it;}}if (cut_segments.empty()) {cout << "0 0\n";boards[op + 1].clear();continue;}// 為了后續合并相鄰區間處理,先對切割出的區間按起點排序sort(cut_segments.begin(), cut_segments.end());// 根據是否滿足 c[i] = i(即 allDistinct 為 true)分別處理if (allDistinct) {// 在全不相同的情況下,每個區間內不同顏色數和顏色段數均等于區間長度int distinct_count = 0, total_segments = 0;for (auto& seg : cut_segments) {int len = seg.second - seg.first + 1;distinct_count += len;total_segments += len;}cout << distinct_count << " " << total_segments << "\n";} else {// ------------------------// 1. 利用塊狀分解“distinctQuery”求多個區間中不同顏色的并集// ------------------------vector<uint64_t> union_bs(W, 0ULL);// 統計所有被切區間的顏色(并集)for (auto& seg : cut_segments) {int a = seg.first, b = seg.second;vector<uint64_t> bs = distinctQuery(a, b);unionBitset(union_bs, bs);}int distinct_count = countBits(union_bs);// ------------------------// 2. 利用線段樹查詢每個被切區間的顏色段數,然后對相鄰區間作合并處理// ------------------------int total_segments = 0;for (auto& seg : cut_segments) {int a = seg.first, b = seg.second;int seg_count, first, last;query(root, a, b, seg_count, first, last);total_segments += seg_count;}// 如果相鄰兩個切割區間原本是連續的且兩端顏色相同,則合并后顏色段數減少1int merged = 0;for (int i = 1; i < (int)cut_segments.size(); i++) {int prev_b = cut_segments[i - 1].second;int curr_a = cut_segments[i].first;if (prev_b + 1 == curr_a) {int dummy;int col1, col2;query(root, prev_b, prev_b, dummy, col1, col1);query(root, curr_a, curr_a, dummy, col2, col2);if (col1 == col2) {merged++;}}}total_segments -= merged;cout << distinct_count << " " << total_segments << "\n";}// 新木板編號為 op+1,記錄本次切下的所有區間boards[op + 1].clear();for (auto& seg : cut_segments) {boards[op + 1].insert(seg);}}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85674.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85674.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85674.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【藍橋杯】包子湊數

包子湊數 題目描述 小明幾乎每天早晨都會在一家包子鋪吃早餐。他發現這家包子鋪有 NN 種蒸籠&#xff0c;其中第 ii 種蒸籠恰好能放 AiAi? 個包子。每種蒸籠都有非常多籠&#xff0c;可以認為是無限籠。 每當有顧客想買 XX 個包子&#xff0c;賣包子的大叔就會迅速選出若干…

pikachu通關教程-目錄遍歷漏洞(../../)

目錄遍歷漏洞也可以叫做信息泄露漏洞、非授權文件包含漏洞等. 原理:目錄遍歷漏洞的原理比較簡單&#xff0c;就是程序在實現上沒有充分過濾用戶輸入的../之類的目錄跳轉符&#xff0c;導致惡意用戶可以通過提交目錄跳轉來遍歷服務器上的任意文件。 這里的目錄跳轉符可以是../…

[概率論基本概念4]什么是無偏估計

關鍵詞&#xff1a;Unbiased Estimation 一、說明 對于無偏和有偏估計&#xff0c;需要了解其敘事背景&#xff0c;是指整體和抽樣的關系&#xff0c;也就是說整體的敘事是從理論角度的&#xff0c;而估計器原理是從實踐角度說事&#xff1b;為了表明概率理論&#xff08;不可…

面試題——計算機網絡:HTTP和HTTPS的區別?

HTTP&#xff08;HyperText Transfer Protocol&#xff09;&#xff1a;作為互聯網上應用最廣泛的網絡通信協議&#xff0c;HTTP是基于TCP/IP協議族的應用層協議。它采用標準的請求-響應模式進行通信&#xff0c;通過簡潔的報文格式&#xff08;包含請求行、請求頭、請求體等&a…

uni-app學習筆記十九--pages.json全局樣式globalStyle設置

pages.json 頁面路由 pages.json 文件用來對 uni-app 進行全局配置&#xff0c;決定頁面文件的路徑、窗口樣式、原生的導航欄、底部的原生tabbar 等。 導航欄高度為 44px (不含狀態欄)&#xff0c;tabBar 高度為 50px (不含安全區)。 它類似微信小程序中app.json的頁面管理部…

SQL思路解析:窗口滑動的應用

目錄 &#x1f3af; 問題目標 第一步&#xff1a;從數據中我們能直接得到什么&#xff1f; 第二步&#xff1a;我們想要的“7天窗口”長什么樣&#xff1f; 第三步&#xff1a;SQL 怎么表達“某一天的前六天”&#xff1f; &#x1f50d;JOIN 比窗口函數更靈活 第四步&am…

解決MyBatis參數綁定中參數名不一致導致的錯誤問題

前言 作為一名Java開發者&#xff0c;我在實際項目中曾多次遇到MyBatis參數綁定的問題。其中最常見的一種情況是&#xff1a;在Mapper接口中定義的參數名與XML映射文件中的占位符名稱不一致&#xff0c;導致運行時拋出Parameter xxx not found類異常。這類問題看似簡單&#x…

黑馬程序員TypeScript課程筆記—類型兼容性篇

類型兼容性的說明 因為傳入的時候只有一個參數 對象之間的類型兼容性 接口之間的類型兼容性 函數之間的類型兼容性&#xff08;函數參數個數&#xff09; 和對象的兼容性正好相反 函數之間的類型兼容性&#xff08;函數參數類型&#xff09; 函數參數的兼容性就不要從接口角度…

智能電視的操作系統可能具備哪些優勢

豐富的應用資源&#xff1a; 操作系統內置了應用商店&#xff0c;提供了豐富的應用資源&#xff0c;涵蓋視頻、游戲、教育等多個領域&#xff0c;滿足不同用戶的多樣化需求。用戶可以輕松下載并安裝所需的應用&#xff0c;享受更多元化的娛樂和學習體驗。 流暢的操作體驗&…

Xget 正式發布:您的高性能、安全下載加速工具!

您可以通過 star 我固定的 GitHub 存儲庫來支持我&#xff0c;謝謝&#xff01;以下是我的一些 GitHub 存儲庫&#xff0c;很有可能對您有用&#xff1a; tzst Xget Prompt Library 原文 URL&#xff1a;https://blog.xi-xu.me/2025/06/02/xget-launch-high-performance-sec…

精美的軟件下載頁面HTML源碼:現代UI與動畫效果的完美結合

精美的軟件下載頁面HTML源碼&#xff1a;現代UI與動畫效果的完美結合 在數字化產品推廣中&#xff0c;一個設計精良的下載頁面不僅能提升品牌專業度&#xff0c;還能顯著提高用戶轉化率。本文介紹的精美軟件下載頁面HTML源碼&#xff0c;通過現代化UI設計與豐富的動畫效果&…

麒麟v10+信創x86處理器離線搭建k8s集群完整過程

前言 最近為某客戶搭建內網的信創環境下的x8s集群&#xff0c;走了一些彎路&#xff0c;客戶提供的環境完全與互聯網分離&#xff0c;通過yum、apt這些直接拉依賴就別想了&#xff0c;用的操作系統和cpu都是國產版本&#xff0c;好在仍然是x86的&#xff0c;不是其他架構&…

Pycharm的使用技巧總結

目錄 一、高效便捷的快捷鍵 二、界面漢化處理 1.設置 2.插件 3.漢化插件安裝 三、修改字體大小、顏色 1.選擇文件-設置 2.選擇編輯器-配色方案-python 3.修改注釋行顏色 4.修改編輯器字體顏色 一、高效便捷的快捷鍵 序號快捷鍵功能場景效果1Ctrl /快速注釋/取消注釋…

安全編碼規范與標準:對比與分析及應用案例

在軟件開發領域&#xff0c;尤其是涉及安全關鍵系統的開發中&#xff0c;遵循編碼規范和標準是確保軟件質量和安全性的重要手段。除了CERT C、CERT Java和MISRA外&#xff0c;還有其他多個與安全相關的編碼規范和標準&#xff0c;以下是一些主要標準的對比說明&#xff1a; 一…

FFmpeg學習筆記

1. 播放器的架構 2. 播放器的渲染流程 3. ffmpeg下載與安裝 3.0 查看PC是否已經安裝了ffmpeg ffmpeg 3.1 下載 wget https://ffmpeg.org/releases/ffmpeg-7.0.tar.gz 3.2 解壓 tar zxvf ffmpeg-7.0.tar.gz && cd ./ffmpeg-7.0 3.3 查看配置文件 ./configure …

大寬帶怎么做

我有10個G的寬帶資源&#xff0c;怎樣運行P2P才能將收益巨大化&#xff0c;主要有以下幾種方式&#xff1a; 1.多設備匯聚模式&#xff1a;使用多臺支持千兆網絡的服務器或專用PCDN設備&#xff08;如N1盒子&#xff09;&#xff0c;將10條寬帶分別接入不同設備&#xff0c;通過…

pytorch基本運算-導數和f-string

引言 在前序對機器學習的探究過程中&#xff0c;我們已經深刻體會到人工智能到處都有微分求導運算&#xff0c;相關文章鏈接包括且不限于&#xff1a; BP神經網絡 邏輯回歸 對于pytorch張量&#xff0c;求導運算必不可少&#xff0c;所以本次就專門來學習一下。 f-string的用…

dvwa4——File Inclusion

LOW: 先隨便點開一個文件&#xff0c;可以觀察到url欄變成這樣&#xff0c;說明?page是dvwa當前關卡用來加載文件的參數 http://10.24.8.35/DVWA/vulnerabilities/fi/?pagefile1.php 我們查看源碼 &#xff0c;沒有什么過濾&#xff0c;直接嘗試訪問其他文件 在url欄的pag…

經典面試題:一文了解常見的緩存問題

在面試過程中&#xff0c;面試官的桌子上擺放著很多高頻的面試題&#xff0c;能否順利回答決定了你面試通過的概率。其中緩存問題就是其中的一份&#xff0c;可以說掌握緩存問題及解決方法是面試前必須準備的內容。那么緩存有什么典型的問題&#xff0c;出現的原因是什么&#…

生產環境中安裝和配置 Nginx 以部署 Flask 應用的詳細指南

在生產環境中部署 Flask 應用時&#xff0c;Nginx 常被用作反向代理服務器&#xff0c;與 WSGI 服務器&#xff08;如 Gunicorn&#xff09;協同工作。Nginx 可以處理靜態文件、提供 SSL/TLS 加密、實現負載均衡等功能。本文將詳細介紹如何在 Ubuntu/Debian 系統上安裝 Nginx&a…