[{"content":" 文章来源：数据库内核月报 2024/01 - MySQL 权限管理\nMySQL 权限简介 MySQL 账号权限（本文聚焦静态权限）决定了账户可执行的操作。日常常见授权方式（如 db 级别 select、table 级别 update）比较直观，但底层权限划分与校验实现更值得系统梳理。\n权限层级分类 MySQL 静态权限按控制范围可分为：\nglobal database table column routines 授权时有两个关键规则：\n高层级授权会向下继承 某些权限仅能在特定层级授权（例如 create user 只能 global） 示例（非法层级授权会报错）：\nmysql\u0026gt; grant create user on db1.* to u1; ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES mysql\u0026gt; grant create routine on db1.t to u1; ERROR 1144 (42000): Illegal GRANT/REVOKE command mysql\u0026gt; grant update(a) on db1.* to u1; ERROR 1144 (42000): Illegal GRANT/REVOKE command 权限存储 不同层级授权会落到不同系统表：\nglobal -\u0026gt; mysql.user db -\u0026gt; mysql.db table -\u0026gt; mysql.tables_priv column -\u0026gt; mysql.columns_priv 权限变更本质上就是更新这些系统表中的记录。\n例如 mysql.user 表结构如下：\n权限变化示例：\n无权限状态：\n授予 global select 后：\n授予列级 update 后：\n权限更新流程 通过 GRANT/REVOKE 更新权限时，可以概括为两步：\n解析并确定本次要更新的权限位 根据授权层级写入对应权限表 权限位表示 MySQL 使用位图表示权限：\n#define SELECT_ACL (1L \u0026lt;\u0026lt; 0) #define INSERT_ACL (1L \u0026lt;\u0026lt; 1) #define UPDATE_ACL (1L \u0026lt;\u0026lt; 2) #define DELETE_ACL (1L \u0026lt;\u0026lt; 3) #define CREATE_ACL (1L \u0026lt;\u0026lt; 4) #define DROP_ACL (1L \u0026lt;\u0026lt; 5) #define RELOAD_ACL (1L \u0026lt;\u0026lt; 6) #define SHUTDOWN_ACL (1L \u0026lt;\u0026lt; 7) #define PROCESS_ACL (1L \u0026lt;\u0026lt; 8) #define FILE_ACL (1L \u0026lt;\u0026lt; 9) 授权层级合法性校验 权限层级匹配在两个阶段检查：\n语法解析阶段先做早期拦截 mysql_grant 执行阶段再做严格层级校验 其中 DB 级授权会检查权限是否属于 DB_ACLS，不匹配会报 DB GRANT and GLOBAL PRIVILEGES 错误。\n权限认证流程（以 SELECT 为例） 执行 SELECT 时会在语义检查阶段进行权限校验，核心链路是：\ncheck_access：先看 user/db 层权限 check_grant：不足再看 table/column 层权限 合并权限后，在字段解析阶段逐列校验 示例：\ncreate table t (a int, b int); grant select(a) on db1.t to u1; select a from t; 此场景下，列级权限需要在后续列解析阶段继续校验，最终在字段处理逻辑中判定当前列是否可访问。\n总结 MySQL 权限体系的核心可以理解为：\n权限模型：分层 + 位图 权限更新：语法解析 + 层级落表 权限认证：按 user -\u0026gt; db -\u0026gt; table -\u0026gt; column 逐层补全与校验 理解这三层结构后，排查授权异常和权限报错会高效很多。\n参考 数据库内核月报 2024/01 原文 ","permalink":"https://eonh1u.github.io/posts/mysql-%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86-2024-01/","summary":"从权限层级、权限存储到权限更新与认证流程，梳理 MySQL 静态权限管理实现。","title":"MySQL 权限管理（2024/01）"},{"content":" 文章来源：数据库内核月报 2023/05 - MySQL · 源码分析 · 鉴权过程\n前言 在整个 MySQL client connection 生命周期中，鉴权过程位于第一步。鉴权完成后，连接进入 command phase，client 才能继续向 server 发送 command。本文聚焦 client 连接时 user/password 的认证过程。\n本文内容基于 MySQL Community 8.0.33。\n鉴权过程概览 MySQL 支持多种鉴权插件，常见有 native_password_authenticate、caching_sha2_password_authenticate。本文先以 native_password 为主线，再补充插件切换场景。\nnative_password 鉴权主流程 mysqld_main() ... connection_event_loop() process_new_connection() thd_prepare_connection(thd) check_connection() acl_authenticate() // 鉴权 while(thd alive) { do_command(); // 鉴权成功后进入 command phase } 连接鉴权交互 Server 发送 initial Handshake（包含 scramble 与 plugin 信息） Client 基于 plugin 对 scramble 处理后返回 Handshake Response Server 校验结果，成功后进入 command phase server 发送 initial Handshake acl_authenticate() auth_plugin_name = default_auth_plugin_name mpvio.scramble[SCRAMBLE_LENGTH] = 1 do_auth_once() prepare plugin auth-\u0026gt;authenticate_user() if (mpvio-\u0026gt;scramble[SCRAMBLE_LENGTH]) generate_user_salt() mpvio-\u0026gt;write_packet() if (mpvio-\u0026gt;packets_written == 0) send_server_handshake_packet() 首次包会构建 Protocol::HandshakeV10，核心字段包括 protocol version、server version、scramble、auth_plugin_name。\nclient 接收 Handshake 并发送 Response csm_read_greeting csm_parse_handshake csm_authenticate() run_plugin_auth() authsm_begin_plugin_auth() auth_plugin-\u0026gt;authenticate_user() vio-\u0026gt;read_packet() scramble(server_scramble_data, mysql-\u0026gt;passwd) vio-\u0026gt;write_packet() prep_client_reply_packet my_net_write() \u0026amp;\u0026amp; net_flush() client 发送时构建 Protocol::HandshakeResponse41，关键字段包括 client_flag、auth_response、client_plugin_name。\nserver 接收 Handshake Response acl_authenticate() do_auth_once() authenticate_user() mpvio-\u0026gt;read_packet() parse_client_handshake_packet() if (check_scramble) return OK 校验成功后，连接进入 command phase。\n切换鉴权插件场景 在 MySQL 8.0.33 中，默认插件通常是 caching_sha2_password。若某个用户实际插件不同（例如 native_password），server 会在首轮响应后发送 Authentication Switch Request，client 切换插件并再次完成认证。\nserver 触发 Auth Switch Request parse_client_handshake_packet() if (mpvio-\u0026gt;acl_user_plugin != mpvio-\u0026gt;plugin) mpvio-\u0026gt;status = MPVIO_EXT::RESTART if (mpvio.status == MPVIO_EXT::RESTART) do_auth_once() send_plugin_request_packet() 第二轮 server 发的是 Protocol::AuthSwitchRequest。\nclient 处理 Auth Switch Request if (mysql-\u0026gt;net.read_pos[0] == 254) // AuthSwitchRequest ctx-\u0026gt;auth_plugin_name = server_send_plugin_name authenticate_user() mpvio-\u0026gt;read_packet() // 读取新的 scramble mpvio-\u0026gt;write_packet() // 回传 AuthSwitchResponse client 回传的是 Protocol::AuthSwitchResponse，不再是 Handshake Response。\nserver 接收 Auth Switch Response acl_authenticate() do_auth_once() mpvio-\u0026gt;read_packet() *buf = protocol-\u0026gt;get_net()-\u0026gt;read_pos if (check_scramble) return OK server 验证成功后，连接同样进入 command phase。\n参考 mysql connection_phase MySQL · 源码分析 · 连接与认证过程 数据库内核月报 2023/05 原文 ","permalink":"https://eonh1u.github.io/posts/mysql-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E9%89%B4%E6%9D%83%E8%BF%87%E7%A8%8B-2023-05/","summary":"梳理 MySQL 连接阶段鉴权流程，覆盖 native_password 与鉴权插件切换场景。","title":"MySQL 源码分析：鉴权过程（2023/05）"},{"content":"DB扫盲ing\n","permalink":"https://eonh1u.github.io/about/","summary":"\u003cp\u003eDB扫盲ing\u003c/p\u003e","title":"关于"},{"content":"plantuml 时序图 a-\u0026gt;b a-\u0026gt;c c--\u0026gt;b 用例图 @startuml User -\u0026gt; (Start) User --\u0026gt; (Use the application) : A small label :Main Admin: ---\u0026gt; (Use the application) : This is\\nyet another\\nlabel @enduml 类图 @startuml skinparam groupInheritance 1 A1 \u0026lt;|-- B1 A2 \u0026lt;|-- B2 A2 \u0026lt;|-- C2 A3 \u0026lt;|-- B3 A3 \u0026lt;|-- C3 A3 \u0026lt;|-- D3 A4 \u0026lt;|-- B4 A4 \u0026lt;|-- C4 A4 \u0026lt;|-- D4 A4 \u0026lt;|-- E4 @enduml 流程图 @startuml :开始; :\u0026#34;步骤1处理\u0026#34;; :\u0026#34;步骤2处理\u0026#34;; if (\u0026#34;条件1判断\u0026#34;) then (true) :条件1成立时执行的动作; if (\u0026#34;分支条件2判断\u0026#34;) then (no) :\u0026#34;条件2不成立时执行的动作\u0026#34;; else if (\u0026#34;条件3判断\u0026#34;) then (yes) :\u0026#34;条件3成立时的动作\u0026#34;; else (no) :\u0026#34;条件3不成立时的动作\u0026#34;; endif endif :\u0026#34;顺序步骤3处理\u0026#34;; endif if (\u0026#34;条件4判断\u0026#34;) then (yes) :\u0026#34;条件4成立的动作\u0026#34;; else if (\u0026#34;条件5判断\u0026#34;) then (yes) :\u0026#34;条件5成立时的动作\u0026#34;; else (no) :\u0026#34;条件5不成立时的动作\u0026#34;; endif endif :结束; @enduml 甘特图 @startgantt [Prototype design] lasts 15 days [Test prototype] lasts 10 days -- All example -- [Task 1 (1 day)] lasts 1 day [T2 (5 days)] lasts 5 days [T3 (1 week)] lasts 1 week [T4 (1 week and 4 days)] lasts 1 week and 4 days [T5 (2 weeks)] lasts 2 weeks @endgantt 对象图 @startuml package foo { object baz } package bar { map A { b *-\u0026gt; foo.baz c =\u0026gt; } } A::c --\u0026gt; foo @enduml 组件图 @startuml package \u0026#34;Some Group\u0026#34; { HTTP - [First Component] [Another Component] } node \u0026#34;Other Groups\u0026#34; { FTP - [Second Component] [First Component] --\u0026gt; FTP } cloud { [Example 1] } database \u0026#34;MySql\u0026#34; { folder \u0026#34;This is my folder\u0026#34; { [Folder 3] } frame \u0026#34;Foo\u0026#34; { [Frame 4] } } [Another Component] --\u0026gt; [Example 1] [Example 1] --\u0026gt; [Folder 3] [Folder 3] --\u0026gt; [Frame 4] @enduml 状态图 @startuml scale 600 width [*] -\u0026gt; State1 State1 --\u0026gt; State2 : Succeeded State1 --\u0026gt; [*] : Aborted State2 --\u0026gt; State3 : Succeeded State2 --\u0026gt; [*] : Aborted state State3 { state \u0026#34;Accumulate Enough Data\\nLong State Name\u0026#34; as long1 long1 : Just a test [*] --\u0026gt; long1 long1 --\u0026gt; long1 : New Data long1 --\u0026gt; ProcessData : Enough Data } State3 --\u0026gt; State3 : Failed State3 --\u0026gt; [*] : Succeeded / Save Result State3 --\u0026gt; [*] : Aborted @enduml 思维导图 @startmindmap * root node * some first level node * second level node * another second level node * another first level node @endmindmap json @startjson { \u0026#34;name\u0026#34; : \u0026#34;huyutuo\u0026#34; } @endjson yaml @startyaml doe: \u0026#34;a deer, a female deer\u0026#34; ray: \u0026#34;a drop of golden sun\u0026#34; pi: 3.14159 xmas: true french-hens: 3 calling-birds: - huey - dewey - louie - fred xmas-fifth-day: calling-birds: four french-hens: 3 golden-rings: 5 partridges: count: 1 location: \u0026#34;a pear tree\u0026#34; turtle-doves: two @endyaml ","permalink":"https://eonh1u.github.io/posts/plantuml/","summary":"\u003ch2 id=\"plantuml\"\u003eplantuml\u003c/h2\u003e\n\u003ch3 id=\"时序图\"\u003e时序图\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-puml\" data-lang=\"puml\"\u003ea-\u0026gt;b\na-\u0026gt;c\nc--\u0026gt;b\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"用例图\"\u003e用例图\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-puml\" data-lang=\"puml\"\u003e@startuml\n\nUser -\u0026gt; (Start)\nUser --\u0026gt; (Use the application) : A small label\n\n:Main Admin: ---\u0026gt; (Use the application) : This is\\nyet another\\nlabel\n\n@enduml\n\u003c/code\u003e\u003c/pre\u003e","title":"plantUML"},{"content":"在之前的服务器上发现安装的nccl，不能正确的运行nccl test测试，在尝试了多种方法之后，发现需要重新编译安装nccl\nhttps://github.com/nvidia/nccl\n按照官方github上说明进行编译安装\napt install build-essential devscripts debhelper fakeroot -y make -j pkg.debian.build dpkg -i build/pkg/deb/*.deb 我的环境中cuda与nccl都是默认路径，因此在编译nccl-test时无需再说明对应路径\nmake MPI=1 MPI_HOME=/usr/local/ 执行上述命令之后，将编译完成的build复制至其他节点，然后即可进行测试\n","permalink":"https://eonh1u.github.io/posts/nccl-test-%E7%8E%AF%E5%A2%83/","summary":"\u003cp\u003e在之前的服务器上发现安装的nccl，不能正确的运行nccl test测试，在尝试了多种方法之后，发现需要重新编译安装nccl\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/nvidia/nccl\"\u003ehttps://github.com/nvidia/nccl\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e按照官方github上说明进行编译安装\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eapt install build-essential devscripts debhelper fakeroot -y \nmake -j pkg.debian.build\ndpkg -i build/pkg/deb/*.deb\n\u003c/code\u003e\u003c/pre\u003e","title":"nccl test 环境"},{"content":"🏆leetcode 记录leetcode中的题目🤡 在此文件中更新🧐\n134.加油站 将每个站点进行处理，得到从当前站点至下个站点能够剩余的汽油，可以将此看为一个最长连续子序列的变形。 只要能够找到从一个点出发，一直相加使得和不为0，这样就满足题目所给出的条件。因为还可能存在不满足的情况，所以最后还需要再判断一下。\nclass Solution { public: int canCompleteCircuit(vector\u0026lt;int\u0026gt;\u0026amp; gas, vector\u0026lt;int\u0026gt;\u0026amp; cost) { int len = gas.size(); int start = 0; int MAX = 0; int now = 0; for (int i = 0; i \u0026lt; len; i++) { now += (gas[i] - cost[i]); if (now \u0026lt; 0) { now = 0; start = i + 1; } if (now \u0026gt; MAX) { MAX = now; } } MAX = 0; for (int i = start; i \u0026lt; len; i++) { MAX += gas[i] - cost[i]; if (MAX \u0026lt; 0) return -1; } for (int i = 0; i \u0026lt; start; i++) { MAX += gas[i] - cost[i]; if (MAX \u0026lt; 0) return -1; } return start; } }; 452. 用最少数量的箭引爆气球 dp做法，复杂度n2 将气球按照l,r升序排序，处理从每个气球出发，能够最多引爆多少气球，可以得到一组数列，数列中a[i] 代码从i出发走一步能够跨越的最大距离，对数列进行处理，就可以得到到达最后一个气球所花费最小的步数。\nclass Solution {public: int findMinArrowShots(vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt;\u0026amp; points) { sort(points.begin(), points.end(), [](const vector\u0026lt;int\u0026gt;\u0026amp; a, const vector\u0026lt;int\u0026gt;\u0026amp; b) { if (a[0] == b[0]) return a[1] \u0026lt; b[1]; else return a[0] \u0026lt; b[0]; }); int len = points.size(); //cout \u0026lt;\u0026lt; \u0026#34;len \u0026#34; \u0026lt;\u0026lt; len \u0026lt;\u0026lt; endl; vector\u0026lt;int\u0026gt; l; for (int i = 0; i \u0026lt; len; i++) { int s = points[i][0]; int e = points[i][1]; int num = 1; for (int j = i + 1; j \u0026lt; len; j++) { if (points[j][0] \u0026lt;= e) { s = max(s, points[j][0]); e = min(e, points[j][1]); num++; } else { break; } } //cout \u0026lt;\u0026lt; \u0026#34;l \u0026#34; \u0026lt;\u0026lt; num \u0026lt;\u0026lt; endl; l.push_back(num); } vector\u0026lt;int\u0026gt; ans(len + 1, 99999); ans[0] = 0; //cout \u0026lt;\u0026lt; \u0026#34;ans size \u0026#34; \u0026lt;\u0026lt; ans.size() \u0026lt;\u0026lt; endl; for (int i = 0; i \u0026lt; len; i++) { for (int j = 1; j \u0026lt;= l[i]; j++) { ans[i + j] = min(ans[i + j], ans[i] + 1); } } return ans[len]; } }; 贪心做法，复杂度nlog 将气球按照r升序排序，从第一个气球出发，气球引爆范围包括r的就可以引爆，然后对升序的气球做同样的处理。\nclass Solution { public: int findMinArrowShots(vector\u0026lt;vector\u0026lt;int\u0026gt;\u0026gt;\u0026amp; points) { sort(points.begin(), points.end(), [](const vector\u0026lt;int\u0026gt;\u0026amp; a, const vector\u0026lt;int\u0026gt;\u0026amp; b) { return a[1] \u0026lt; b[1]; }); int len = points.size(); int ans = 0; for (int i = 0; i \u0026lt; len; i++) { ans++; int now = points[i][1]; while(i \u0026lt; len \u0026amp;\u0026amp; points[i][0] \u0026lt;= now) { i++; } i--; } return ans; } }; 222. 完全二叉树的节点个数 二分查找\n/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public: int countNodes(TreeNode* root) { int h = 0; TreeNode* tmp = root; while(tmp != nullptr) { h++; tmp = tmp -\u0026gt; left; } int ans = pow(2, h - 1) - 1; tmp = root; for (int i = 1; i \u0026lt;= h; i++) { TreeNode* p = tmp; if (tmp != nullptr) if (f(p, h - i)) { tmp = tmp -\u0026gt; right; ans += pow(2, h - 1 - i) + 0.5; } else { tmp = tmp -\u0026gt; left; } } return ans; } bool f(TreeNode* tmp, int h) { if (h == 0) { return tmp != nullptr; } tmp = tmp -\u0026gt; right; for (int i = 1; i \u0026lt; h; i++) { tmp = tmp -\u0026gt; left; } return tmp != nullptr; } }; 暴力递归\n/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int countNodes(TreeNode* root) { if (root == nullptr) { return 0; } return countNodes(root -\u0026gt; left) + countNodes(root -\u0026gt; right) + 1; } }; 1370. 上升下降字符串 统计每个字符出现的次数，然后从头到尾，从尾到头扫描，直至所有字符都被输出\nclass Solution { public: string sortString(string s) { vector\u0026lt;int\u0026gt; v(26,0); int len = s.length(); for (int i = 0; i \u0026lt; len; i++) { v[s[i] - \u0026#39;a\u0026#39;]++; } string ans = \u0026#34;\u0026#34;; while(len) { for (int i = 0; i \u0026lt; 26; i++) { if (v[i] \u0026gt; 0) { v[i]--; ans += char(\u0026#39;a\u0026#39; + i); len--; } } for (int i = 25; i \u0026gt;= 0; i--) { if (v[i] \u0026gt; 0) { v[i]--; ans += char(\u0026#39;a\u0026#39; + i); len--; } } } return ans; } }; 164. 最大间距 暴力排序，然后遍历(nlogn)\n将数组划分为不同的区间，每块区间的长度为（MAX - MIN)/(n - 1）,然后遍历相邻的区间，用后面区间的最小值 - 前面区间的最大值，最终ans为所有差中的最大值\nclass Solution { public: int maximumGap(vector\u0026amp; nums) { int len = nums.size(); if (len \u0026lt; 2) return 0; int Max = *max_element(nums.begin(), nums.end()); int Min = *min_element(nums.begin(), nums.end()); int d = max(1, (Max - Min) / (len - 1)); int bucketSize = (Max - Min) / d + 1; vector\u0026lt;pair\u0026lt;long long, long long\u0026raquo; v(bucketSize, {999999999, -1}); for (int i = 0; i \u0026lt; len; i++) { int index = (nums[i] - Min) / d; v[index].first = min(v[index].first, nums[i] * 1ll); v[index].second = max(v[index].second, nums[i] * 1ll); } long long ans = 0; int pre = -1; for (int i = 0; i \u0026lt; bucketSize; i++) { if (v[i].second == -1) continue; if (pre != -1 ) { ans = max(ans, v[i].first - v[pre].second); } pre = i; } return ans; } };\n# [454. 四数相加 II](https://leetcode-cn.com/problems/4sum-ii/) 1.将AB，CD分别处理成两个单独的vector，然后排序，转换为两数相加 class Solution { public: int fourSumCount(vector\u0026amp; A, vector\u0026amp; B, vector\u0026amp; C, vector\u0026amp; D) { int len = A.size(); vector a; vector b; for (int i = 0; i \u0026lt; len; i++) { for (int j = 0; j \u0026lt; len; j++) { a.push_back(A[i] + B[j]); b.push_back(C[i] + D[j]); } } sort(a.begin(), a.end()); sort(b.begin(), b.end());\nlen = a.size(); //cout \u0026lt;\u0026lt; \u0026quot;len \u0026quot; \u0026lt;\u0026lt; len \u0026lt;\u0026lt; endl; int s = 0; int e = len - 1; int ans = 0; while(s \u0026lt; len || e \u0026gt;= 0) { //cout \u0026lt;\u0026lt; \u0026quot;s \u0026quot; \u0026lt;\u0026lt; s \u0026lt;\u0026lt; \u0026quot; e \u0026quot; \u0026lt;\u0026lt; e \u0026lt;\u0026lt; endl; int now = a[s] + b[e]; if (now == 0) { int tmp = a[s]; int l1 = 0, l2 = 0; while(s \u0026lt; len \u0026amp;\u0026amp; a[s] == tmp) { s++; l1++; } tmp = b[e]; while(e \u0026gt;= 0 \u0026amp;\u0026amp; b[e] == tmp) { e--; l2++; } ans += l1 * l2; } else if(now \u0026lt; 0) { s++; } else { e--; } //cout \u0026lt;\u0026lt; \u0026quot;ans1 \u0026quot; \u0026lt;\u0026lt; ans \u0026lt;\u0026lt; endl; if (s == len) { while(e \u0026gt;= 0) { now = a[len - 1] + b[e]; if (now == 0) { ans++; e--; } if (now \u0026lt; 0) { break; } } break; } if (e \u0026lt; 0) { while(s \u0026lt; len) { now = a[s] + b[0]; if (now == 0) { ans++; s++; } if (now \u0026gt; 0) { break; } } break; } } return ans; } };\n2.对AB，CD分别进行处理，存在map中 class Solution { public: int fourSumCount(vector\u0026amp; A, vector\u0026amp; B, vector\u0026amp; C, vector\u0026amp; D) { unordered_map\u0026lt;int, int\u0026gt; countAB; for (int\u0026amp; u: A) { for (int\u0026amp; v: B) { countAB[u + v]++; } } int ans = 0; for (int\u0026amp; u: C) { for (int\u0026amp; v: D) { if (countAB.count(-u - v)) { ans += countAB[-u - v]; } } } return ans; } };\n# [5615. 使数组互补的最少操作次数](https://leetcode-cn.com/problems/minimum-moves-to-make-array-complementary/) 首先很容易想到的一个点是去遍历所有的可能[2, 2 * limit],然后去判断每一对的和为X时，最少的操作次数为多少。 对于每一对数的和变为X需要的操作次数，取一对数中较小的数为a, 较大的数为b，再加上a+b, 我们可以得到5个点，分别为2, a + 1, a + b, b + limit, 2 * limit。 X的取值范围 与 一对数的和变为X的关系为: [2, a + 1) : 2 [a, a + b) : 1 [a + b, a + b] : 0 [a + b + 1, b + limit] : 1 [b + limit + 1, 2 * limit) : 2 所以当确定X之后，我们便能很快的求得一对数的和变为X的操作数。 如果暴力遍历[2, 2 * limit]去判断的话，复杂度为O(n2)，很明显会超时。 下面就是如何在一部分去优化复杂度。 这里可以类比题目[452. 用最少数量的箭引爆气球](https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/)，我们是可以得到最终的结果一定是不会是一个区间的中间值，一定是所有的（a, a + b, a + b + 1, b + limit + 1）中存在的，所以我们可以将搜索范围缩小至所有的（a, a + b, a + b + 1, b + limit + 1）中。 但是所有的（a, a + b, a + b + 1, b + limit + 1）中的个数是有可能与2 * limit相近的，直接去遍历所有出现过的点，复杂度没有降下来。 下面我们去判断针对一对数的情况，在不同的区间，一对数的和变为X的操作数k是怎么变化的，我们参考上面提到的 **X的取值范围 与 一对数的和变为X的关系** 设X的取值开始为2，k也为2 然后增大为a时，k为1 然后增大为a + b时， k为0 然后增大为a + b + 1时， k为1 然后增大为b + limit + 1时，k为2 对于一组数我们可以得到这样的变化特性，我们可以将多对数的这些数字叠加起来，将**迭代判断转化为线性变化扫描**，这样将复杂度降到O(n) class Solution { public: int minMoves(vector\u0026amp; nums, int limit) { int len = nums.size(); map\u0026lt;int, int\u0026gt; m; for (int i = 0; i \u0026lt; len / 2; i++) { int Min = min(nums[i], nums[len - 1 - i]); int Max = max(nums[i], nums[len - 1 - i]); int l = Min + 1; int r = Max + limit; int sum = nums[i] + nums[len - 1 - i]; m[l]\u0026ndash;; m[sum]\u0026ndash;; m[sum + 1]++; m[r + 1]++; } int ans = 999999; int now = len; for (auto \u0026amp;s : m) { now += s.second; ans = min(ans, now); } return ans; } };\n# [1673. 找出最具竞争力的子序列](https://leetcode-cn.com/problems/find-the-most-competitive-subsequence/) 最容易想到的一种方法是，在[0,len-k+1)个数中找到最小的（设最小的数下标为l1），然后即为ans的第一个数，然后从[l1 + 1, len-k + 2)中找到最小的，然后依次循环，直到找到k个数。 这样复杂度为O(n2) 可以使用单调栈来优化复杂度，首先对前len-k+1个数进行处理，得到单调递增的栈，然后再依次处理剩下的k-1个数，注意最终单调栈中的数字个数必须大于等于k 在此代码中利用双向队列去实现单调栈 class Solution { public: vector mostCompetitive(vector\u0026amp; nums, int k) { deque v; int len = nums.size(); for (int i = 0; i \u0026lt; len - k + 1; i++) { while (!v.empty() \u0026amp;\u0026amp; nums[i] \u0026lt; v.back()) { v.pop_back(); } v.push_back(nums[i]); }\nvector\u0026lt;int\u0026gt; ans; int lsum = v.size() - 1; for (int i = len - k + 1; i \u0026lt; len; i++) { while(lsum \u0026gt; 0 \u0026amp;\u0026amp; nums[i] \u0026lt; v.back()) { v.pop_back(); lsum--; } v.push_back(nums[i]); } for (int i = 0; i \u0026lt; k; i++) { ans.push_back(v[i]); } return ans; } };\n# 842. 将数组拆分成斐波那契序列 因为数据最长只有200，又因为数字的范围在int范围内，所以我们可以暴力一点。 用循环来枚举出数列的前两项，然然后再依次判断是否可以构成数列。 ```class Solution { public: vector\u0026lt;int\u0026gt; splitIntoFibonacci(string S) { int len = S.length(); vector\u0026lt;int\u0026gt; ans; if (len \u0026lt; 3) return vector\u0026lt;int\u0026gt;(0); for (int i = 1; i \u0026lt; len - 2 \u0026amp;\u0026amp; i \u0026lt; 12; i++) { for (int j = i + 1; j \u0026lt; len - 1 \u0026amp;\u0026amp; j - i \u0026lt; 12; j++) { ans.clear(); string s1 = S.substr(0, i); string s2 = S.substr(i, j - i); long long num1 = b(s1); long long num2 = b(s2); //cout \u0026lt;\u0026lt; \u0026#34;num1 \u0026#34; \u0026lt;\u0026lt; num1 \u0026lt;\u0026lt; \u0026#34; num2 \u0026#34; \u0026lt;\u0026lt; num2 \u0026lt;\u0026lt; endl; if (num1 == -1 || num2 == -1) { continue; } ans.push_back((int)num1); ans.push_back((int)num2); bool flag = true; int now = j; while(now \u0026lt; len \u0026amp;\u0026amp; flag) { long long num3 = num1 + num2; //cout \u0026lt;\u0026lt; \u0026#34;num3 \u0026#34; \u0026lt;\u0026lt; num3 \u0026lt;\u0026lt; endl; if (num3 \u0026gt;= (1ll\u0026lt;\u0026lt;32)) { flag = false; break; } int ll = l(num3); //cout \u0026lt;\u0026lt; \u0026#34;l num3 \u0026#34; \u0026lt;\u0026lt; num3 \u0026lt;\u0026lt; endl; if (now + ll - 1 \u0026gt;= len) { flag = false; break; } string s3 = S.substr(now, ll); if (b(s3) != num3) { flag = false; break; } ans.push_back((int)num3); num1 = num2; num2 = num3; now = now + ll; } if (!flag) { continue; } if (now \u0026gt;= len) { return ans; } } } return vector\u0026lt;int\u0026gt;(0); } long long f(string\u0026amp; s) { long long ans = 0; for (auto c : s) { ans = ans * 10 + int(c - \u0026#39;0\u0026#39;); } return ans; } long long b(string\u0026amp; s) { int len = s.length(); if (len \u0026gt; 1 \u0026amp;\u0026amp; s[0] == \u0026#39;0\u0026#39;) { return -1; } long long tmp = f(s); if (tmp \u0026gt;= 0 \u0026amp;\u0026amp; tmp \u0026lt;= (1ll\u0026lt;\u0026lt;32 - 1)) { return tmp; } else { return -1; } } int l(long long x) { if(x == 0) return 1; int ans = 0; while(x) { ans++; x /= 10; } return ans; } }; 649. Dota2 参议院 用list处理一下就行，之前很少用到list，这次熟悉了一次。\npublic: string predictPartyVictory(string senate) { int suma = 0; int sumb = 0; string aa = \u0026#34;Radiant\u0026#34;; string bb = \u0026#34;Dire\u0026#34;; list\u0026lt;char\u0026gt; l; for (auto c : senate) { if (c == \u0026#39;R\u0026#39;) { suma++; } else { sumb++; } l.push_back(c); } int a = 0, b = 0; int nowa = 0, nowb = 0; while(nowa \u0026lt; suma \u0026amp;\u0026amp; nowb \u0026lt; sumb) { for(auto it = l.begin(); it != l.end(); it++) { //cout \u0026lt;\u0026lt; *it \u0026lt;\u0026lt; endl; if (*it == \u0026#39;R\u0026#39;) { if (a \u0026gt; 0) { it = l.erase(it); it--; nowa++; a--; } else { b++; } } else { if (b \u0026gt; 0) { it = l.erase(it); it--; nowb++; b--; } else { a++; } } } } if(nowa == suma) { return bb; } else { return aa; } } }; 376. 摆动序列 构建状态转移方程式，二维的dp数组，dp[i][0]代表i之前的最后为升序的最长长度，dp[i][1]代表i之前的最后为降序的最长长度。 最后也可以减少空间复杂度\nclass Solution { public: int wiggleMaxLength(vector\u0026lt;int\u0026gt;\u0026amp; nums) { if (nums.size() == 0) return 0; int up = 1; int down = 1; for (int i = 1; i \u0026lt; nums.size(); i++) { if (nums[i] \u0026gt; nums[i - 1]) { up = max(down + 1, up); } else if (nums[i] \u0026lt; nums[i - 1]) { down = max(up + 1, down); } } return max(up, down); } }; ","permalink":"https://eonh1u.github.io/posts/leetcode/","summary":"\u003ch1 id=\"leetcode\"\u003e🏆leetcode\u003c/h1\u003e\n\u003cp\u003e记录leetcode中的题目🤡\n在此文件中更新🧐\u003c/p\u003e","title":"leetcode"},{"content":"若执行ssh-add /path/to/xxx.pem是出现这个错误:Could not open a connection to your authentication agent，则先执行如下命令即可： ssh-agent bash 然后执行ssh-add xxx.pem 如果出现ssh “permissions are too open” error，则执行chmod命令修改xx.pem文件权限 chmod 400 ~/.ssh/id_rsa 或者 chmod 600 ~/.ssh/id_rsa\n这样配置之后，有可能每次进来终端，都需要重新运行上述命令才能够连接上服务器 所以在/etc/bash.bashrc 末尾添加\nif [ -f ~/.agent.env ];then . ~/.agent.env \u0026gt;/dev/null if ! kill -0 $SSH_AGENT_PID \u0026gt;/dev/null 2\u0026gt;\u0026amp;1; then echo \u0026#34; stale agent file found. Spawning new agent....\u0026#34; eval `ssh-agent | tee ~/.agent.env ` if [[ $? -eq 0 ]] ;then echo \u0026#34;agent ok!\u0026#34; fi ssh-add \u0026#39;xxxx.xx\u0026#39; # your private key if [[ $? -eq 0 ]] ; then echo \u0026#34;key add ok!\u0026#34; fi fi else eval ` ssh-agent |tee ~/.agent.env` \u0026gt;/dev/null 2\u0026gt;\u0026amp;1 if [[ $? -eq 0 ]] ;then echo \u0026#34;agent ok!\u0026#34; fi ssh-add \u0026#39;xxxx.xx\u0026#39; # your private key if [[ $? -eq 0 ]] ; then echo \u0026#34;key add ok!\u0026#34; fi fi 在有些服务器上修改/etc/bash.bashrc不生效，可以在 /etc/profile.d/路径下添加sh文件，文件内容如上，这样便可以进行ssh无密码登录服务器\n","permalink":"https://eonh1u.github.io/posts/ssh-%E7%A7%81%E9%92%A5%E8%BF%9E%E6%8E%A5%E6%9C%8D%E5%8A%A1%E5%99%A8%E8%AE%B0%E5%BD%95/","summary":"\u003cp\u003e若执行ssh-add /path/to/xxx.pem是出现这个错误:Could not open a connection to your authentication agent，则先执行如下命令即可：\n　　ssh-agent bash\n然后执行ssh-add xxx.pem\n如果出现ssh “permissions are too open” error，则执行chmod命令修改xx.pem文件权限\nchmod 400 ~/.ssh/id_rsa   或者 chmod 600 ~/.ssh/id_rsa\u003c/p\u003e","title":"ssh 私钥连接服务器记录"},{"content":"修改ECS开机逻辑问题记录 修改原因 之前的ECS开机在enqueue阶段实现。逻辑为：如果作业是pending状态，并且作业所需的资源大于集群的空闲资源。这个时候就为该任务开启一台ECS节点。 假设作业所需的资源为R1，目前集群的空闲资源为R2，在之前的逻辑中会选择一个资源为R3的ECS节点，使得R3 + R2 \u0026gt;= R1。这样就出现了一个问题，我们的想法是使得作业能在新开启的节点上运行的（目前只考虑单机作业), 即新开启的ECS必须满足R3 \u0026gt;= R1, 这样看来，之前的开机逻辑是存在问题的，在实际中我们也碰到了这种情况。 所以我们需要将ECS开机逻辑进行更改。\n开机逻辑设计 将开机逻辑移至enqueue的下一个阶段，allocate。 allocate阶段当初在进行分配node前会获取node列表，获取node列表时会只选择开启的node节点 allNodes := util.GetReadyNodeList(ssn.Nodes) 将此部分进行更改为返回所有的节点 allNodes := util.GetAllNodeList(ssn.Nodes)\n在predicate筛选阶段，因为对于未开启节点，在predicate阶段有几种方式都会将未开启的节点过滤，因此再此只判断node节点资源能够满足task要求，能够满足判断通过node筛选\nprioritize阶段对通过predicate筛选节点进行打分，选择最合适的节点。因为之前在此阶段的节点都是已经开启的节点，现在未开启的节点加入进来，需要对打分进行一些修改，目前我们修改打分机制使得优先选择已经开启的节点\n对节点打分之后，可以选择出来一个最高分的节点，如果此节点为未开启的节点，我们将此节点放入toStartNode中，toStartNode中的节点都会在判断job的所有task数目（或者满足最少task数目)都满足需求之后，在stmt.commit之前进行开启。 toStartNode = append(toStartNode, node)\n碰到的问题 1.在node节点开启之后，马上进行commit，会出现Pod Update plugin resources failed due to requested number of devices unavailable for nvidia.com/gpu. Requested: 1, Available: 0, which is unexpected.错误， 这里初次判断是因为在节点开启之前就进行allocate会产生一些错误，后面通过读代码发现问题不在这里，此问题产生的原因是因为在stmt.commit时，k8s将task提交至node时，获取的node gpu数目不足以满足作业需求，所以才产生了此错误。\n在判断节点是否满足需求时，我们已经得到了满足需求的结果，为什么进行提交之后会返回错误那，通过测试(在节点开启之后，sleep5分钟，然后再进行commit)发现作业commit之后能够成功的进行调度，所以感觉是k8s对于gpu资源的获取延迟产生的问题，所以我们需要在allocate部分感知到k8s什么时候能够获取的node上正确的gpu信息。\n在allocate部分，通过对代码进行修改使得能够通过session得到scheduler对应的kubeclient，我们通过kubeclient可以得到node信息(暴露私有成员，修改sheduler 部署权限） nodeinfo, err := kubeclient.CoreV1().Nodes().Get(node.Name, metav1.GetOptions{})\n通过在程序中进行检测，发现在node节点从关闭状态至开启状态，然后开启之后的过程中，Allocatable的gpu数目会发生1-\u0026gt;0-\u0026gt;1的变化，k8s原生的资源则不会产生此变化，不会出现值变为0的情况\ngpuinfo := nodeinfo.Status.Allocatable[\u0026#34;nvidia.com/gpu\u0026#34;].DeepCopy() gpunum, f := gpuinfo.AsInt64(） 猜测出现此情况的原因是k8s通过Device Plugins来感知gpu资源，在节点开启之后，不能及时的更新gpu数目，但此处为何会产生这种变化尚不明确，以后可以再加深探索一下。\n目前的测试得到在1-\u0026gt;0-\u0026gt;1之后，进行commit则不会产生此种错误(在Node ready condition状态为true并且gpu num == 1之后进行commit之后也不会出现错误)\n目前系统中判断node gpu信息准备完成是根据nodeinfo.Status.Conditions中NodeReady为true，并且gpu数目 \u0026gt; 0 （对于cpu节点，等于0也判断为true)\n修改具体细节 通过session获取kubeclient修改代码 session中有cache信息,schedulerCache实现了cache并且其中含有kubeclient，因此可以通过session来得到client。\n因为kubeclient在cache中为私有成员，所以chche接口中添加GetKubeclient()方法 修改pkg/scheduler/cache/cache.go文件\n//通过defaultBinder得到kubeclient func (sc *SchedulerCache) GetKubeclient() *kubernetes.Clientset { return sc.kubeclient } 修改pkg/scheduler/framework/session.go文件\n//GetClient Get client from session func (ssn *Session) GetClient() *kubernetes.Clientset { return ssn.cache.GetKubeclient() } 修改完代码之后便可以通过session来得到kubeclient，从而可以访问node，pod等信息。\n在测试中发现通过kubeclient获取node信息失败，发现原因是在部署scheduler时限制了client的功能 修改installer/volcano-development.yaml文件,添加对nodes的get操作，便可以获取node信息\nresources: [\u0026#34;nodes\u0026#34;] // verbs: [\u0026#34;list\u0026#34;, \u0026#34;watch\u0026#34;] verbs: [\u0026#34;list\u0026#34;, \u0026#34;watch\u0026#34;, \u0026#34;get\u0026#34;] ","permalink":"https://eonh1u.github.io/posts/volcano%E7%B3%BB%E7%BB%9F%E4%BF%AE%E6%94%B9%E8%AE%B0%E5%BD%95/","summary":"\u003ch1 id=\"修改ecs开机逻辑问题记录\"\u003e修改ECS开机逻辑问题记录\u003c/h1\u003e\n\u003ch2 id=\"修改原因\"\u003e修改原因\u003c/h2\u003e\n\u003cp\u003e之前的ECS开机在enqueue阶段实现。逻辑为：如果作业是pending状态，并且作业所需的资源大于集群的空闲资源。这个时候就为该任务开启一台ECS节点。\n假设作业所需的资源为R1，目前集群的空闲资源为R2，在之前的逻辑中会选择一个资源为R3的ECS节点，使得R3 + R2 \u0026gt;= R1。这样就出现了一个问题，我们的想法是使得作业能在新开启的节点上运行的（目前只考虑单机作业), 即新开启的ECS必须满足R3 \u0026gt;= R1, 这样看来，之前的开机逻辑是存在问题的，在实际中我们也碰到了这种情况。\n所以我们需要将ECS开机逻辑进行更改。\u003c/p\u003e","title":"volcano ECS开机逻辑修改记录"},{"content":"STL-C++ 本文是关于c++中STL库中的一些记录，主要是因为之前在网上找到关于STL的资料太过简洁，并且只停留在如何使用函数，对于底层具体实现较少，所以想自己对这些知识记录一下，当然我目前对STL库了解也不深入，以后如果会有新的了解的话，会继续更新。\nvector vector定义 template\u0026lt;class _Ty, class _Ax\u0026gt; class vector : public _Vector_val\u0026lt;_Ty, _Ax\u0026gt; { // varying size array of values public: /********/ protected: pointer _Myfirst; // pointer to beginning of array pointer _Mylast; // pointer to current end of sequence pointer _Myend; // pointer to end of array }; vector底层采用的数据结构是一段连续的线性空间，vector可以当做被封装之后的数组，提供了一些方法使得我们更好的对数组进行操作。 _Myfirst代表数组的第一个元素的首地址 _Mylast代表数组的最后一个元素的末尾字节地址 _Myend代表vector整个容器所占内存空间的末尾空间\ncapacity()与size() size()返回vector中目前的元素个数 capacity()返回目前vector中容量大小 简单点可以认为 size = _Mylast - _Myfirst capacity = _Myend - _Myfirst\n扩容 当_Mylast == _Myend时，会引起vector的扩容，vector中扩容方式为每次2倍空间增长(普遍为2倍，貌似还有1.5倍) 在新增数据的时候，会分配一块更大的内存，将原来的数据拷贝至新内存空间，然后将旧内存空间释放掉，然后再插入新的元素。值得注意是，在对vector操作时如果引起了vector中空间重新配置，则先前的迭代器失效。 如果采用常数的扩容方式时扩容操作的均摊时间复杂度为O(N)，而采用倍数增长的方式则可以使得均摊的复杂度变为O(1),这里大家可以举一些例子算一下，不在赘述。 为什么采用2倍的方式进行扩容而不是3倍，4倍，这里参考知乎的一个回答： 这里也有讨论扩容因子K（即每次扩容的倍数)对于时间以及空间上的影响: 从时间上考虑K越大越好，从空间考虑K越小越好 我们来看一下K = 2时的情况。 每次扩容后capacity的情况如下：1，2，4，8，16，32 …….. 当我们释放了4的空间，我们寻找8的新空间，再次扩容，释放8，寻找16。。 仔细分析，第5次扩容时，需要寻找16的新空间，第4次释放了8，第3次释放了4，第2次释放了2，第1次释放了1，所以 1 + 2 + 4 + 8 = 15 \u0026lt; 16，也就意味着，之前释放的空间，永远无法被下一次的扩容利用，这对内存与cache是非常不友好的。 我们再来看一下K = 1.5的情况。 每次扩容之后capacity的情况为：1，2，3，4，6，9，13，19，28 …… 再按刚才的思路分析一遍，1 + 2 \u0026gt;= 3; 2 + 3 + 4 \u0026gt;= 6; 6 + 9 \u0026gt;= 13 ……. 所以，当K为1.5时，显然对内存和cache要友好很多，至少从容量上来说，是存在重复利用的可能性的。\npush_back()与emplace_back() push_back与emplace_back作用都是将一个元素放入vector末尾，但是emplace_back效率要比push_back高。 push_back放入元素时，会首先执构造函数，然后将构造好的元素拷贝或者移动到vector中，而emplace_back则是在vector的内存空间中直接创建元素，省去了拷贝或者移动的消耗。（拷贝或者移动与push_back()中是左值还是右值有关,左值为拷贝，右值为移动)\nvector元素存放位置 vector中元素存放位置在堆上，被分配到栈上的元素在被push_back或者emplace_back时都会被放到堆上，如果想让vector中存储栈上的元素，可以将vector中的元素设置为原来元素的指针\n","permalink":"https://eonh1u.github.io/posts/stl-c++/","summary":"\u003ch1 id=\"stl-c\"\u003eSTL-C++\u003c/h1\u003e\n\u003cp\u003e本文是关于c++中STL库中的一些记录，主要是因为之前在网上找到关于STL的资料太过简洁，并且只停留在如何使用函数，对于底层具体实现较少，所以想自己对这些知识记录一下，当然我目前对STL库了解也不深入，以后如果会有新的了解的话，会继续更新。\u003c/p\u003e\n\u003ch2 id=\"vector\"\u003evector\u003c/h2\u003e\n\u003ch3 id=\"vector定义\"\u003evector定义\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003etemplate\u0026lt;class _Ty,\n    class _Ax\u0026gt;\n    class vector\n        : public _Vector_val\u0026lt;_Ty, _Ax\u0026gt;\n    {   // varying size array of values\npublic:\n    /********/\nprotected:\n    pointer _Myfirst;   // pointer to beginning of array\n    pointer _Mylast;    // pointer to current end of sequence\n    pointer _Myend; // pointer to end of array\n    };\n\u003c/code\u003e\u003c/pre\u003e","title":"STL-C++"},{"content":"最近状态很低迷，效率底下，也反思了最近自己的不足。在这里记录一下，一年后再来比较，希望自己能改变不足\n不足 抗拒写文档 不管是对于code前的设计文档，或者是code完成之后的总结，对一些知识的总结，内心总会有一种抗拒心里，不愿意去写。\n觉得写文档浪费时间，对于已经熟悉的知识不愿意去写去总结。 虽然确实当时对于某些知识点是熟练掌握的，但是不去记录，不去再次复盘，后面也遗忘的很快。 对于要总结的知识点其实不熟，更加有种抗拒心里去总结。 这种心理造成的影响其实是更坏的，像是有一种逃避的心理，不敢去面对新知识，掩耳盗铃。 code前的设计文档 之前写的程序都是小代码，不需要详细的设计文档等。code前也只是在脑中过一遍，具体的在code中再去修改，对于代码量小的文件或者项目来说是无所谓的，影响很小，对于稍微大点的项目来说，提前想好代码框架则是尤为重要的。 28原则是正确的，应该去花80%的时间去提前完善好代码框架与详细的文档，20%的时间去code，在code的过程中发现问题再去修改文档。 现在自己可能是反过来的，20%时间思考，80%直接上手code，因此在过程中也浪费掉了很多时间。 在大量无用app上浪费时间过多 对于游戏我觉得没有问题，可以休闲娱乐玩一下。但是最近在大量无用的app上浪费掉了太多时间，导致于每天进展很少，熬夜也久，然后每天就会焦虑。 原因首先是自己自控能力较弱，其次是在平常中没有对自己做好计划\n收藏太多东西，却不去执行 碰到一个觉得有用的文章，网页，书籍，会收藏起来，但是重新翻起来再去学习的次数却很少\n思路不清晰 写代码时候思路不清晰，逻辑处理的很繁琐，将简单问题处理的很复杂\n改进 每天强迫自己写文档 不管文档是否内容丰富，先强迫自己每天15分钟写文档进行每天的自我总结。 每周写一篇技术文档 用量的手段先养成自己的习惯\n控制自己玩手机的时间 这个只能在平时多注意，少在奶头乐上花费时间\n开始清理收藏夹，开始执行自己的计划 将收藏夹清理整理一遍 无用的直接删除，对于希望执行的进行分类，划好deadline\n","permalink":"https://eonh1u.github.io/posts/%E5%89%96%E6%9E%90/","summary":"\u003cp\u003e最近状态很低迷，效率底下，也反思了最近自己的不足。在这里记录一下，一年后再来比较，希望自己能改变不足\u003c/p\u003e\n\u003ch2 id=\"不足\"\u003e不足\u003c/h2\u003e\n\u003ch3 id=\"抗拒写文档\"\u003e抗拒写文档\u003c/h3\u003e\n\u003cp\u003e不管是对于code前的设计文档，或者是code完成之后的总结，对一些知识的总结，内心总会有一种抗拒心里，不愿意去写。\u003c/p\u003e","title":"剖析"},{"content":"其实最近一直有刷题，但是因为题目都比较简单的原因并没有贴到博客上。这样做是因为感觉之前的状态有点像是在为了努力而努力，没有想清楚自己真正想干什么。 最近也一直在思考以后想要做什么，大概率是分布式存储，分布式系统相关的底层架构了。 写这篇博客另一方面也是想激励一下自己，不要再继续颓废下去了，应该想清楚自己该做什么，并且自己应该怎么调节一下自己的心态，让自己不受其他人的影响，尤其是不要跟一些垃圾人多辩解，没有一点好处。 纸上得来终觉浅，绝知此事要躬行，从大佬博客中看到了这句话，一瞬间突然发现自己目前的状态缺了什么，code，多多实践，写一些小项目来更深刻的理解一下。 我想成为什么样？ 希望自己能够不焦虑的去努力，一步一步朝着目标前进。 希望自己能够自律，减少耗费在手机与游戏上的时间。 努力吧。\n","permalink":"https://eonh1u.github.io/posts/%E6%88%91%E6%83%B3%E6%88%90%E4%B8%BA%E4%BB%80%E4%B9%88%E6%A0%B7/","summary":"\u003cp\u003e其实最近一直有刷题，但是因为题目都比较简单的原因并没有贴到博客上。这样做是因为感觉之前的状态有点像是在为了努力而努力，没有想清楚自己真正想干什么。\n最近也一直在思考以后想要做什么，大概率是分布式存储，分布式系统相关的底层架构了。\n写这篇博客另一方面也是想激励一下自己，不要再继续颓废下去了，应该想清楚自己该做什么，并且自己应该怎么调节一下自己的心态，让自己不受其他人的影响，尤其是不要跟一些垃圾人多辩解，没有一点好处。\n纸上得来终觉浅，绝知此事要躬行，从大佬博客中看到了这句话，一瞬间突然发现自己目前的状态缺了什么，code，多多实践，写一些小项目来更深刻的理解一下。\n\u003cstrong\u003e我想成为什么样？\u003c/strong\u003e\n希望自己能够不焦虑的去努力，一步一步朝着目标前进。\n希望自己能够自律，减少耗费在手机与游戏上的时间。\n努力吧。\u003c/p\u003e","title":"我想成为什么样"},{"content":"A:Yet Another Dividing into Teams 题目： You are a coach of a group consisting of 𝑛 students. The 𝑖-th student has programming skill 𝑎𝑖. All students have distinct programming skills. You want to divide them into teams in such a way that:\nNo two students 𝑖 and 𝑗 such that |𝑎𝑖−𝑎𝑗|=1 belong to the same team (i.e. skills of each pair of students in the same team have the difference strictly greater than 1); the number of teams is the minimum possible. You have to answer 𝑞 independent queries.\nInput The first line of the input contains one integer 𝑞 (1≤𝑞≤100) — the number of queries. Then 𝑞 queries follow.\nThe first line of the query contains one integer 𝑛 (1≤𝑛≤100) — the number of students in the query. The second line of the query contains 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤100, all 𝑎𝑖 are distinct), where 𝑎𝑖 is the programming skill of the 𝑖-th student.\nOutput For each query, print the answer on it — the minimum number of teams you can form if no two students 𝑖 and 𝑗 such that |𝑎𝑖−𝑎𝑗|=1 may belong to the same team (i.e. skills of each pair of students in the same team has the difference strictly greater than 1)\nExample input\n4 4 2 10 1 20 2 3 6 5 2 3 4 99 100 1 42 output\n2 1 2 1 题解 暴力即可\n代码 #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int a[110]; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--){ int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt;n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); int ans = 1; sort(a,a +n); for(int i = 1; i \u0026lt; n;i++) if(a[i] - a[i-1] == 1){ ans++; break; } printf(\u0026#34;%d\\n\u0026#34;,ans); } return 0; } B Books Exchange 题目 The only difference between easy and hard versions is constraints.\nThere are 𝑛 kids, each of them is reading a unique book. At the end of any day, the 𝑖-th kid will give his book to the 𝑝𝑖-th kid (in case of 𝑖=𝑝𝑖 the kid will give his book to himself). It is guaranteed that all values of 𝑝𝑖 are distinct integers from 1 to 𝑛 (i.e. 𝑝 is a permutation). The sequence 𝑝 doesn\u0026rsquo;t change from day to day, it is fixed.\nFor example, if 𝑛=6 and 𝑝=[4,6,1,3,5,2] then at the end of the first day the book of the 1-st kid will belong to the 4-th kid, the 2-nd kid will belong to the 6-th kid and so on. At the end of the second day the book of the 1-st kid will belong to the 3-th kid, the 2-nd kid will belong to the 2-th kid and so on.\nYour task is to determine the number of the day the book of the 𝑖-th child is returned back to him for the first time for every 𝑖 from 1 to 𝑛.\nConsider the following example: 𝑝=[5,1,2,4,3]. The book of the 1-st kid will be passed to the following kids:\nafter the 1-st day it will belong to the 5-th kid, after the 2-nd day it will belong to the 3-rd kid, after the 3-rd day it will belong to the 2-nd kid, after the 4-th day it will belong to the 1-st kid. So after the fourth day, the book of the first kid will return to its owner. The book of the fourth kid will return to him for the first time after exactly one day.\nYou have to answer 𝑞 independent queries.\nInput The first line of the input contains one integer 𝑞 (1≤𝑞≤200) — the number of queries. Then 𝑞 queries follow.\nThe first line of the query contains one integer 𝑛 (1≤𝑛≤200) — the number of kids in the query. The second line of the query contains 𝑛 integers 𝑝1,𝑝2,…,𝑝𝑛 (1≤𝑝𝑖≤𝑛, all 𝑝𝑖 are distinct, i.e. 𝑝 is a permutation), where 𝑝𝑖 is the kid which will get the book of the 𝑖-th kid.\nOutput For each query, print the answer on it: 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛, where 𝑎𝑖 is the number of the day the book of the 𝑖-th child is returned back to him for the first time in this query.\nExample input\n6 5 1 2 3 4 5 3 2 3 1 6 4 6 2 1 5 3 1 1 4 3 4 1 2 5 5 1 2 4 3 output\n1 1 1 1 1 3 3 3 2 3 3 2 1 3 1 2 2 2 2 4 4 4 1 4 题解 并查集记录属于哪一个集合即可。\n代码 #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int a[200010]; int p[200010]; int f[200010]; set\u0026lt;int\u0026gt; s; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--){ int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 1; i \u0026lt;= n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); f[i] = i; } for(int i = 1; i \u0026lt;= n; i++) { if(f[i] != i) continue; int ans = 1; int now = i; while(a[now] != i){ f[now] = i; now = a[now]; ans++; } p[i] = ans; } for(int i = 1; i \u0026lt;= n; i++){ if(f[i] == i) printf(\u0026#34;%d \u0026#34;, p[i]); else{ printf(\u0026#34;%d \u0026#34;,p[f[i]]); } } printf(\u0026#34;\\n\u0026#34;); } return 0; } C Good Numbers 题目: The only difference between easy and hard versions is the maximum value of 𝑛.\nYou are given a positive integer number 𝑛. You really love good numbers so you want to find the smallest good number greater than or equal to 𝑛.\nThe positive integer is called good if it can be represented as a sum of distinct powers of 3 (i.e. no duplicates of powers of 3 are allowed).\nFor example:\n30 is a good number: 30=33+31, 1 is a good number: 1=30, 12 is a good number: 12=32+31, but 2 is not a good number: you can\u0026rsquo;t represent it as a sum of distinct powers of 3 (2=30+30), 19 is not a good number: you can\u0026rsquo;t represent it as a sum of distinct powers of 3 (for example, the representations 19=32+32+30=32+31+31+31+30 are invalid), 20 is also not a good number: you can\u0026rsquo;t represent it as a sum of distinct powers of 3 (for example, the representation 20=32+32+30+30 is invalid). Note, that there exist other representations of 19 and 20 as sums of powers of 3 but none of them consists of distinct powers of 3.\nFor the given positive integer 𝑛 find such smallest 𝑚 (𝑛≤𝑚) that 𝑚 is a good number.\nYou have to answer 𝑞 independent queries.\nInput The first line of the input contains one integer 𝑞 (1≤𝑞≤500) — the number of queries. Then 𝑞 queries follow.\nThe only line of the query contains one integer 𝑛 (1≤𝑛≤1018).\nOutput For each query, print such smallest integer 𝑚 (where 𝑛≤𝑚) that 𝑚 is a good number.\nExample input\n8 1 2 6 13 14 3620 10000 1000000000000000000 output\n1 3 9 13 27 6561 19683 1350851717672992089 题解： 转换为三进制，找到第一个为2的位置，然后在2之前找到第一个为0的位置，然后置为1，后面的全部置为0\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int a[100]; long long POW(long long x, long long z) { long long ans = 1; long long now = x; while(z){ if(z\u0026amp;1) ans *= now; now = now * now; z \u0026gt;\u0026gt;= 1; } return ans; } int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--){ long long n; scanf(\u0026#34;%lld\u0026#34;, \u0026amp;n); long long p = n; int len = 0; while(n){ a[len] = n %3; n /= 3; len++; } int sta = -1; for(int i = 0; i \u0026lt; len; i++) { if(a[i] == 2) sta = i; } if(sta == -1){ printf(\u0026#34;%lld\\n\u0026#34;,p); } else{ int t = 0,i; for(i = sta + 1; i \u0026lt; len; i++){ if(a[i] == 0){ t = i; a[i] = 1; break; } } if(i == len) { printf(\u0026#34;%lld\\n\u0026#34;, POW(3,i)); } else{ long long ans = 0; for(int j = t; j \u0026lt; len; j++){ if(a[j] == 1) { ans += POW(3,j); } } printf(\u0026#34;%lld\\n\u0026#34;, ans); } } } return 0; } D Too Many Segments 题目： The only difference between easy and hard versions is constraints.\nYou are given 𝑛 segments on the coordinate axis 𝑂𝑋. Segments can intersect, lie inside each other and even coincide. The 𝑖-th segment is [𝑙𝑖;𝑟𝑖] (𝑙𝑖≤𝑟𝑖) and it covers all integer points 𝑗 such that 𝑙𝑖≤𝑗≤𝑟𝑖.\nThe integer point is called bad if it is covered by strictly more than 𝑘 segments.\nYour task is to remove the minimum number of segments so that there are no bad points at all.\nInput The first line of the input contains two integers 𝑛 and 𝑘 (1≤𝑘≤𝑛≤200) — the number of segments and the maximum number of segments by which each integer point can be covered.\nThe next 𝑛 lines contain segments. The 𝑖-th line contains two integers 𝑙𝑖 and 𝑟𝑖 (1≤𝑙𝑖≤𝑟𝑖≤200) — the endpoints of the 𝑖-th segment.\nOutput In the first line print one integer 𝑚 (0≤𝑚≤𝑛) — the minimum number of segments you need to remove so that there are no bad points.\nIn the second line print 𝑚 distinct integers 𝑝1,𝑝2,…,𝑝𝑚 (1≤𝑝𝑖≤𝑛) — indices of segments you remove in any order. If there are multiple answers, you can print any of them.\nExamples input\n7 2 11 11 9 11 7 8 8 9 7 8 9 11 7 9 output\n3 1 4 7 input\n5 1 29 30 30 30 29 29 28 30 30 30 output\n3 1 2 4 input\n6 1 2 3 3 3 2 3 2 2 2 3 2 3 output\n4 1 3 5 6 题解： 贪心按照lr增序进行排序，然后记录最大的出现次数为k次的位置，只通过了easy版本，暴力进行统计的，hard版本可以用线段树或优先队列A，待补题。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; struct point{ int l,r; int status; int sum; }; point p[200010]; bool cmp(point a, point b){ if(a.r != b.r) return a.r \u0026lt; b.r; else{ return a.l \u0026lt; b.l; } } set\u0026lt;int\u0026gt; s; int main() { int n,k; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;n, \u0026amp;k); for(int i = 1; i \u0026lt;= n; i++){ scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;p[i].l, \u0026amp;p[i].r); p[i].status = i; } sort(p + 1, p + n + 1, cmp); int now = 0; int ans = 0; int end = 0; for(int i = 1; i \u0026lt;= n; i++){ // printf(\u0026#34;l %d r %d\\n\u0026#34;, p[i].l, p[i].r); if(p[i].l \u0026lt;= now) { ans++; s.insert(p[i].status); // printf(\u0026#34;insert\\n\u0026#34;); } else{ for(int j = i - 1; j \u0026gt; end; j--){ if(p[j].r \u0026gt;= p[i].l){ p[j].sum++; if(p[j].sum == k){ now = p[j].r; end = j; break; } } } p[i].sum++; if(p[i].sum == k){ now = p[i].r; end = i; } } // printf(\u0026#34;now %d\\n\u0026#34;, now); } set\u0026lt;int\u0026gt;::iterator it; printf(\u0026#34;%d\\n\u0026#34;, ans); for(it = s.begin(); it != s.end(); it++) printf(\u0026#34;%d \u0026#34;, *it); return 0; } E By Elevator or Stairs 题目 You are planning to buy an apartment in a 𝑛-floor building. The floors are numbered from 1 to 𝑛 from the bottom to the top. At first for each floor you want to know the minimum total time to reach it from the first (the bottom) floor.\nLet:\n𝑎𝑖 for all 𝑖 from 1 to 𝑛−1 be the time required to go from the 𝑖-th floor to the (𝑖+1)-th one (and from the (𝑖+1)-th to the 𝑖-th as well) using the stairs; 𝑏𝑖 for all 𝑖 from 1 to 𝑛−1 be the time required to go from the 𝑖-th floor to the (𝑖+1)-th one (and from the (𝑖+1)-th to the 𝑖-th as well) using the elevator, also there is a value 𝑐 — time overhead for elevator usage (you need to wait for it, the elevator doors are too slow!). In one move, you can go from the floor you are staying at 𝑥 to any floor 𝑦 (𝑥≠𝑦) in two different ways:\nIf you are using the stairs, just sum up the corresponding values of 𝑎𝑖. Formally, it will take ∑𝑖=𝑚𝑖𝑛(𝑥,𝑦)𝑚𝑎𝑥(𝑥,𝑦)−1𝑎𝑖 time units. If you are using the elevator, just sum up 𝑐 and the corresponding values of 𝑏𝑖. Formally, it will take 𝑐+∑𝑖=𝑚𝑖𝑛(𝑥,𝑦)𝑚𝑎𝑥(𝑥,𝑦)−1𝑏𝑖 time units. You can perform as many moves as you want (possibly zero).\nSo your task is for each 𝑖 to determine the minimum total time it takes to reach the 𝑖-th floor from the 1-st (bottom) floor.\nInput The first line of the input contains two integers 𝑛 and 𝑐 (2≤𝑛≤2⋅105,1≤𝑐≤1000) — the number of floors in the building and the time overhead for the elevator rides.\nThe second line of the input contains 𝑛−1 integers 𝑎1,𝑎2,…,𝑎𝑛−1 (1≤𝑎𝑖≤1000), where 𝑎𝑖 is the time required to go from the 𝑖-th floor to the (𝑖+1)-th one (and from the (𝑖+1)-th to the 𝑖-th as well) using the stairs.\nThe third line of the input contains 𝑛−1 integers 𝑏1,𝑏2,…,𝑏𝑛−1 (1≤𝑏𝑖≤1000), where 𝑏𝑖 is the time required to go from the 𝑖-th floor to the (𝑖+1)-th one (and from the (𝑖+1)-th to the 𝑖-th as well) using the elevator.\nOutput Print 𝑛 integers 𝑡1,𝑡2,…,𝑡𝑛, where 𝑡𝑖 is the minimum total time to reach the 𝑖-th floor from the first floor if you can perform as many moves as you want.\nExamples input\n10 2 7 6 18 6 16 18 1 17 17 6 9 3 10 9 1 10 1 5 output\n0 7 13 18 24 35 36 37 40 45 input\n10 1 3 2 3 1 3 3 1 4 1 1 2 3 4 4 1 2 1 3 output\n0 2 4 7 8 11 13 14 16 17 题解 dp 状态转移看代码\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int a[200010]; int b[200010]; int dp[200010][2]; int main() { int n,c; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;n,\u0026amp;c); for(int i = 1; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); for(int i = 1; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;b[i]); dp[0][1] = c; for(int i = 1; i \u0026lt; n; i++){ dp[i][0] = min(dp[i - 1][0] + a[i], dp[i-1][1] + a[i]); dp[i][1] = min(dp[i - 1][0] + b[i] + c, dp[i - 1][1] + b[i]); } for(int i = 0; i \u0026lt; n;i++) printf(\u0026#34;%d \u0026#34;,min(dp[i][0],dp[i][1])); return 0; } ","permalink":"https://eonh1u.github.io/posts/cf-595-div3/","summary":"\u003ch1 id=\"ayet-another-dividing-into-teams\"\u003eA:Yet Another Dividing into Teams\u003c/h1\u003e\n\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eYou are a coach of a group consisting of 𝑛 students. The 𝑖-th student has programming skill 𝑎𝑖. All students have distinct programming skills. You want to divide them into teams in such a way that:\u003c/p\u003e\n\u003cp\u003eNo two students 𝑖 and 𝑗 such that |𝑎𝑖−𝑎𝑗|=1 belong to the same team (i.e. skills of each pair of students in the same team have the difference strictly greater than 1);\nthe number of teams is the minimum possible.\nYou have to answer 𝑞 independent queries.\u003c/p\u003e","title":"cf-595-div3"},{"content":"A: Integer Points 题目： DLS and JLS are bored with a Math lesson. In order to entertain themselves, DLS took a sheet of paper and drew 𝑛 distinct lines, given by equations 𝑦=𝑥+𝑝𝑖 for some distinct 𝑝1,𝑝2,…,𝑝𝑛.\nThen JLS drew on the same paper sheet 𝑚 distinct lines given by equations 𝑦=−𝑥+𝑞𝑖 for some distinct 𝑞1,𝑞2,…,𝑞𝑚.\nDLS and JLS are interested in counting how many line pairs have integer intersection points, i.e. points with both coordinates that are integers. Unfortunately, the lesson will end up soon, so DLS and JLS are asking for your help.\nInput The first line contains one integer 𝑡 (1≤𝑡≤1000), the number of test cases in the input. Then follow the test case descriptions.\nThe first line of a test case contains an integer 𝑛 (1≤𝑛≤10^5), the number of lines drawn by DLS.\nThe second line of a test case contains 𝑛 distinct integers 𝑝𝑖 (0≤𝑝𝑖≤10^9) describing the lines drawn by DLS. The integer 𝑝𝑖 describes a line given by the equation 𝑦=𝑥+𝑝𝑖.\nThe third line of a test case contains an integer 𝑚 (1≤𝑚≤10^5), the number of lines drawn by JLS.\nThe fourth line of a test case contains 𝑚 distinct integers 𝑞𝑖 (0≤𝑞𝑖≤10^9) describing the lines drawn by JLS. The integer 𝑞𝑖 describes a line given by the equation 𝑦=−𝑥+𝑞𝑖.\nThe sum of the values of 𝑛 over all test cases in the input does not exceed 105. Similarly, the sum of the values of 𝑚 over all test cases in the input does not exceed 105.\nIn hacks it is allowed to use only one test case in the input, so 𝑡=1 should be satisfied.\nOutput For each test case in the input print a single integer — the number of line pairs with integer intersection points.\nExample input\n3 3 1 3 2 2 0 3 1 1 1 1 1 2 1 1 output\n3 1 0 Note The picture shows the lines from the first test case of the example. Black circles denote intersection points with integer coordinates. 题解： pi与qi同为奇数或者同为偶数时才会有整数的交点。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--) { long long ans = 0; long long sum[2][2]; sum[0][0]=0;sum[0][1]=0; sum[1][0]=0;sum[1][1]=0; int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); while(n--) { int a; scanf(\u0026#34;%d\u0026#34;, \u0026amp;a); if(a%2==1){ sum[0][0]++; //printf(\u0026#34;%d\\n\u0026#34;,sum[0][0]); } else sum[0][1]++; } int m; scanf(\u0026#34;%d\u0026#34;, \u0026amp;m); while(m--) { int a; scanf(\u0026#34;%d\u0026#34;, \u0026amp;a); if(a%2==1) sum[1][0]++; else sum[1][1]++; } ans = sum[0][0]*sum[1][0] + sum[0][1] * sum[1][1]; printf(\u0026#34;%lld\\n\u0026#34;, ans); } return 0; } B Grow The Tree 题目： Gardener Alexey teaches competitive programming to high school students. To congratulate Alexey on the Teacher\u0026rsquo;s Day, the students have gifted him a collection of wooden sticks, where every stick has an integer length. Now Alexey wants to grow a tree from them.\nThe tree looks like a polyline on the plane, consisting of all sticks. The polyline starts at the point (0,0). While constructing the polyline, Alexey will attach sticks to it one by one in arbitrary order. Each stick must be either vertical or horizontal (that is, parallel to 𝑂𝑋 or 𝑂𝑌 axis). It is not allowed for two consecutive sticks to be aligned simultaneously horizontally or simultaneously vertically. See the images below for clarification.\nAlexey wants to make a polyline in such a way that its end is as far as possible from (0,0). Please help him to grow the tree this way.\nNote that the polyline defining the form of the tree may have self-intersections and self-touches, but it can be proved that the optimal answer does not contain any self-intersections or self-touches.\nInput The first line contains an integer 𝑛 (1≤𝑛≤100000) — the number of sticks Alexey got as a present.\nThe second line contains 𝑛 integers 𝑎1,…,𝑎𝑛 (1≤𝑎𝑖≤10000) — the lengths of the sticks.\nOutput Print one integer — the square of the largest possible distance from (0,0) to the tree end.\nExamples input\n3 1 2 3 output\n26 input\n4 1 1 2 2 output\n20 Note The following pictures show optimal trees for example tests. The squared distance in the first example equals 5⋅5+1⋅1=26, and in the second example 4⋅4+2⋅2=20. 题解： 对数组排序，前n/2的总和与剩余的总和即是ans\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int a[100010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); long long p1 = 0,sum =0; for(int i = 0; i \u0026lt; n ;i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); sum +=a[i]; } sort(a, a+n); for(int i = 0; i \u0026lt; n/2;i++) { p1 += a[i]; } sum -= p1; long long ans = p1*p1+sum*sum; printf(\u0026#34;%lld\u0026#34;,ans); return 0; } D1. The World Is Just a Programming Task (Easy Version) 题目： This is an easier version of the problem. In this version, 𝑛≤500.\nVasya is an experienced developer of programming competitions\u0026rsquo; problems. As all great minds at some time, Vasya faced a creative crisis. To improve the situation, Petya gifted him a string consisting of opening and closing brackets only. Petya believes, that the beauty of the bracket string is a number of its cyclical shifts, which form a correct bracket sequence.\nTo digress from his problems, Vasya decided to select two positions of the string (not necessarily distinct) and swap characters located at this positions with each other. Vasya will apply this operation exactly once. He is curious what is the maximum possible beauty he can achieve this way. Please help him.\nWe remind that bracket sequence 𝑠 is called correct if:\n𝑠 is empty; 𝑠 is equal to \u0026ldquo;(𝑡)\u0026rdquo;, where 𝑡 is correct bracket sequence; 𝑠 is equal to 𝑡1𝑡2, i.e. concatenation of 𝑡1 and 𝑡2, where 𝑡1 and 𝑡2 are correct bracket sequences. For example, \u0026ldquo;(()())\u0026rdquo;, \u0026ldquo;()\u0026rdquo; are correct, while \u0026ldquo;)(\u0026rdquo; and \u0026ldquo;())\u0026rdquo; are not.\nThe cyclical shift of the string 𝑠 of length 𝑛 by 𝑘 (0≤𝑘\u0026lt;𝑛) is a string formed by a concatenation of the last 𝑘 symbols of the string 𝑠 with the first 𝑛−𝑘 symbols of string 𝑠. For example, the cyclical shift of string \u0026ldquo;(())()\u0026rdquo; by 2 equals \u0026ldquo;()(())\u0026rdquo;.\nCyclical shifts 𝑖 and 𝑗 are considered different, if 𝑖≠𝑗.\nInput The first line contains an integer 𝑛 (1≤𝑛≤500), the length of the string.\nThe second line contains a string, consisting of exactly 𝑛 characters, where each of the characters is either \u0026ldquo;(\u0026rdquo; or \u0026ldquo;)\u0026rdquo;.\nOutput The first line should contain a single integer — the largest beauty of the string, which can be achieved by swapping some two characters.\nThe second line should contain integers 𝑙 and 𝑟 (1≤𝑙,𝑟≤𝑛) — the indices of two characters, which should be swapped in order to maximize the string\u0026rsquo;s beauty.\nIn case there are several possible swaps, print any of them.\nExamples input\n10 ()()())(() output\n5 8 7 input\n12 )(()(()())() output\n4 5 10 input\n6 )))(() output\n0 1 1 Note In the first example, we can swap 7-th and 8-th character, obtaining a string \u0026ldquo;()()()()()\u0026rdquo;. The cyclical shifts by 0,2,4,6,8 of this string form a correct bracket sequence.\nIn the second example, after swapping 5-th and 10-th character, we obtain a string \u0026ldquo;)(())()()(()\u0026rdquo;. The cyclical shifts by 11,7,5,3 of this string form a correct bracket sequence.\nIn the third example, swap of any two brackets results in 0 cyclical shifts being correct bracket sequences.\n题解： 暴力求解，在交换ij之后，计算前缀和，计算最小值，求出最小值出现的次数，即为每种交换后，所得到的值，取最大值即可。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; char s[510]; char tmp[510]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); scanf(\u0026#34;%s\u0026#34;, s); int now = 0; for(int i = 0; i \u0026lt; n; i++){ if(s[i] == \u0026#39;(\u0026#39;) now++; else { now--; } } if(now != 0){ printf(\u0026#34;0\\n1 1\u0026#34;); return 0; } int x=0, y= 0, ans = 0; for(int i = 0; i \u0026lt; n; i++) for(int j = 0; j \u0026lt;n;j++){ int p = 0; strcpy(tmp,s); swap(tmp[i],tmp[j]); int MIN = 999; now = 0; for(int k = 0; k \u0026lt; n ;k++){ if(tmp[k] == \u0026#39;(\u0026#39;) now++; else{ now--; } MIN = min(now,MIN); } now = 0; for(int k = 0; k \u0026lt; n ;k++){ if(tmp[k] == \u0026#39;(\u0026#39;) now++; else{ now--; } if(now == MIN) p++; } if(p \u0026gt; ans){ ans = p; x = i; y = j; } } printf(\u0026#34;%d\\n\u0026#34;,ans); printf(\u0026#34;%d %d\u0026#34;,x+1,y+1); return 0; } ","permalink":"https://eonh1u.github.io/posts/cf-594-div2/","summary":"\u003ch1 id=\"a-integer-points\"\u003eA: Integer Points\u003c/h1\u003e\n\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eDLS and JLS are bored with a Math lesson. In order to entertain themselves, DLS took a sheet of paper and drew 𝑛 distinct lines, given by equations 𝑦=𝑥+𝑝𝑖 for some distinct 𝑝1,𝑝2,…,𝑝𝑛.\u003c/p\u003e\n\u003cp\u003eThen JLS drew on the same paper sheet 𝑚 distinct lines given by equations 𝑦=−𝑥+𝑞𝑖 for some distinct 𝑞1,𝑞2,…,𝑞𝑚.\u003c/p\u003e\n\u003cp\u003eDLS and JLS are interested in counting how many line pairs have integer intersection points, i.e. points with both coordinates that are integers. Unfortunately, the lesson will end up soon, so DLS and JLS are asking for your help.\u003c/p\u003e","title":"cf-594-div2"},{"content":"A:Stones 题目： Alice is playing with some stones.\nNow there are three numbered heaps of stones. The first of them contains 𝑎 stones, the second of them contains 𝑏 stones and the third of them contains 𝑐 stones.\nEach time she can do one of two operations:\ntake one stone from the first heap and two stones from the second heap (this operation can be done only if the first heap contains at least one stone and the second heap contains at least two stones);\ntake one stone from the second heap and two stones from the third heap (this operation can be done only if the second heap contains at least one stone and the third heap contains at least two stones). She wants to get the maximum number of stones, but she doesn\u0026rsquo;t know what to do. Initially, she has 0 stones. Can you help her?\nInput The first line contains one integer 𝑡 (1≤𝑡≤100) — the number of test cases. Next 𝑡 lines describe test cases in the following format:\nLine contains three non-negative integers 𝑎, 𝑏 and 𝑐, separated by spaces (0≤𝑎,𝑏,𝑐≤100) — the number of stones in the first, the second and the third heap, respectively.\nIn hacks it is allowed to use only one test case in the input, so 𝑡=1 should be satisfied.\nOutput Print 𝑡 lines, the answers to the test cases in the same order as in the input. The answer to the test case is the integer — the maximum possible number of stones that Alice can take after making some operations.\nExample input\n3 3 4 5 1 0 5 5 3 2 output\n9 0 6 Note For the first test case in the first test, Alice can take two stones from the second heap and four stones from the third heap, making the second operation two times. Then she can take one stone from the first heap and two stones from the second heap, making the first operation one time. The summary number of stones, that Alice will take is 9. It is impossible to make some operations to take more than 9 stones, so the answer is 9.\n题解： b与c能进行多少操作就取多少，然后剩下的b与a看能够取多少，然后取。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--){ int a,b,c; scanf(\u0026#34;%d%d%d\u0026#34;, \u0026amp;a, \u0026amp;b, \u0026amp;c); int ans = 0; if(b \u0026lt; c/2){ ans = b * 3; } else{ ans += c/2 * 3; b -= c/2; if(a \u0026lt; b/2) ans += a * 3; else { ans += b/2 *3; } } printf(\u0026#34;%d\\n\u0026#34;, ans); } return 0; } B：Alice and the List of Presents 题目： Alice got many presents these days. So she decided to pack them into boxes and send them to her friends.\nThere are 𝑛 kinds of presents. Presents of one kind are identical (i.e. there is no way to distinguish two gifts of the same kind). Presents of different kinds are different (i.e. that is, two gifts of different kinds are distinguishable). The number of presents of each kind, that Alice has is very big, so we can consider Alice has an infinite number of gifts of each kind.\nAlso, there are 𝑚 boxes. All of them are for different people, so they are pairwise distinct (consider that the names of 𝑚 friends are written on the boxes). For example, putting the first kind of present into the first box but not into the second box, is different from putting the first kind of present into the second box but not into the first box.\nAlice wants to pack presents with the following rules:\nShe won\u0026rsquo;t pack more than one present of each kind into the same box, so each box should contain presents of different kinds (i.e. each box contains a subset of 𝑛 kinds, empty boxes are allowed); For each kind at least one present should be packed into some box. Now Alice wants to know how many different ways to pack the presents exists. Please, help her and calculate this number. Since the answer can be huge, output it by modulo 109+7.\nSee examples and their notes for clarification.\nInput The first line contains two integers 𝑛 and 𝑚, separated by spaces (1≤𝑛,𝑚≤109) — the number of kinds of presents and the number of boxes that Alice has.\nOutput Print one integer — the number of ways to pack the presents with Alice\u0026rsquo;s rules, calculated by modulo 109+7\nExamples input\n1 3 output\n7 input\n2 2 output\n9 Note In the first example, there are seven ways to pack presents: {1}{}{} {}{1}{} {}{}{1} {1}{1}{} {}{1}{1} {1}{}{1} {1}{1}{1} In the second example there are nine ways to pack presents: {}{1,2} {1}{2} {1}{1,2} {2}{1} {2}{1,2} {1,2}{} {1,2}{1} {1,2}{2} {1,2}{1,2} For example, the way {2}{2} is wrong, because presents of the first kind should be used in the least one box.\n题解： pow(pow(2,m)-1),n) + 快速幂\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; const long long mod = 1e9+7; long long mi(long long x, long long z) { long long ans = 1; long long now = x; while(z) { if(z \u0026amp; 1) ans = (ans * now) %mod; z \u0026gt;\u0026gt;= 1; now = (now * now) % mod; } return ans; } int main() { long long n,m; scanf(\u0026#34;%lld%lld\u0026#34;, \u0026amp;n, \u0026amp;m); long long now = (mi(2,m) - 1 + mod) % mod; long long ans = (mi(now,n)) % mod; printf(\u0026#34;%lld\\n\u0026#34;, ans); return 0; } C:Labs 题目： In order to do some research, 𝑛2 labs are built on different heights of a mountain. Let\u0026rsquo;s enumerate them with integers from 1 to 𝑛2, such that the lab with the number 1 is at the lowest place, the lab with the number 2 is at the second-lowest place, …, the lab with the number 𝑛2 is at the highest place.\nTo transport water between the labs, pipes are built between every pair of labs. A pipe can transport at most one unit of water at a time from the lab with the number 𝑢 to the lab with the number 𝑣 if 𝑢\u0026gt;𝑣.\nNow the labs need to be divided into 𝑛 groups, each group should contain exactly 𝑛 labs. The labs from different groups can transport water to each other. The sum of units of water that can be sent from a group 𝐴 to a group 𝐵 is equal to the number of pairs of labs (𝑢,𝑣) such that the lab with the number 𝑢 is from the group 𝐴, the lab with the number 𝑣 is from the group 𝐵 and 𝑢\u0026gt;𝑣. Let\u0026rsquo;s denote this value as 𝑓(𝐴,𝐵) (i.e. 𝑓(𝐴,𝐵) is the sum of units of water that can be sent from a group 𝐴 to a group 𝐵).\nFor example, if 𝑛=3 and there are 3 groups 𝑋, 𝑌 and 𝑍: 𝑋={1,5,6},𝑌={2,4,9} and 𝑍={3,7,8}. In this case, the values of 𝑓 are equal to:\n𝑓(𝑋,𝑌)=4 because of 5→2, 5→4, 6→2, 6→4, 𝑓(𝑋,𝑍)=2 because of 5→3, 6→3, 𝑓(𝑌,𝑋)=5 because of 2→1, 4→1, 9→1, 9→5, 9→6, 𝑓(𝑌,𝑍)=4 because of 4→3, 9→3, 9→7, 9→8, 𝑓(𝑍,𝑋)=7 because of 3→1, 7→1, 7→5, 7→6, 8→1, 8→5, 8→6, 𝑓(𝑍,𝑌)=5 because of 3→2, 7→2, 7→4, 8→2, 8→4. Please, divide labs into 𝑛 groups with size 𝑛, such that the value min𝑓(𝐴,𝐵) over all possible pairs of groups 𝐴 and 𝐵 (𝐴≠𝐵) is maximal.\nIn other words, divide labs into 𝑛 groups with size 𝑛, such that minimum number of the sum of units of water that can be transported from a group 𝐴 to a group 𝐵 for every pair of different groups 𝐴 and 𝐵 (𝐴≠𝐵) as big as possible.\nNote, that the example above doesn\u0026rsquo;t demonstrate an optimal division, but it demonstrates how to calculate the values 𝑓 for some division.\nIf there are many optimal divisions, you can find any.\nInput The only line contains one number 𝑛 (2≤𝑛≤300).\nOutput Output 𝑛 lines:\nIn the 𝑖-th line print 𝑛 numbers, the numbers of labs of the 𝑖-th group, in any order you want.\nIf there are multiple answers, that maximize the minimum number of the sum of units of water that can be transported from one group the another, you can print any.\nExample input\n3 output\n2 8 5 9 3 4 7 6 1 Note In the first test we can divide 9 labs into groups {2,8,5},{9,3,4},{7,6,1}.\nFrom the first group to the second group we can transport 4 units of water (8→3,8→4,5→3,5→4).\nFrom the first group to the third group we can transport 5 units of water (2→1,8→7,8→6,8→1,5→1).\nFrom the second group to the first group we can transport 5 units of water (9→2,9→8,9→5,3→2,4→2).\nFrom the second group to the third group we can transport 5 units of water (9→7,9→6,9→1,3→1,4→1).\nFrom the third group to the first group we can transport 4 units of water (7→2,7→5,6→2,6→5).\nFrom the third group to the second group we can transport 4 units of water (7→3,7→4,6→3,6→4).\nThe minimal number of the sum of units of water, that can be transported from one group to another is equal to 4. It can be proved, that it is impossible to make a better division.\n题解： 每次取数组的两边以及中间位置。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int main() { int n; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); if(n % 2 == 0){ int p = n*n; for(int i = 0; i \u0026lt; n; i++){ for(int j = 1; j \u0026lt;= n/2; j++) printf(\u0026#34;%d %d \u0026#34;, i * (n/2) + j,p + 1 -(i * (n/2) + j)); printf(\u0026#34;\\n\u0026#34;); } } else{ int l = 0,r = 0,s = 0; int mid = (1 + n*n)/2; int p = n * n; for(int i = 0; i \u0026lt; n; i++){ for(int j = 1; j \u0026lt;= n/2; j++) printf(\u0026#34;%d %d \u0026#34;, i * (n/2) + j,p + 1 -(i * (n/2) + j)); if(s == 0) { printf(\u0026#34;%d\\n\u0026#34;,mid); s = 1; } else if(l == r){ l++; printf(\u0026#34;%d\\n\u0026#34;,mid - l); } else{ r++; printf(\u0026#34;%d\\n\u0026#34;,mid + r); } } } return 0; } ","permalink":"https://eonh1u.github.io/posts/cf-593-div2/","summary":"\u003ch1 id=\"astones\"\u003eA:Stones\u003c/h1\u003e\n\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eAlice is playing with some stones.\u003c/p\u003e\n\u003cp\u003eNow there are three numbered heaps of stones. The first of them contains 𝑎 stones, the second of them contains 𝑏 stones and the third of them contains 𝑐 stones.\u003c/p\u003e\n\u003cp\u003eEach time she can do one of two operations:\u003c/p\u003e\n\u003cp\u003etake one stone from the first heap and two stones from the second heap (this operation can be done only if the first heap contains at least one stone and the second heap contains at least two stones);\u003c/p\u003e","title":"cf-593-div2"},{"content":"A:Balanced Rating Changes 题目： Another Codeforces Round has just finished! It has gathered 𝑛 participants, and according to the results, the expected rating change of participant 𝑖 is 𝑎𝑖. These rating changes are perfectly balanced — their sum is equal to 0.\nUnfortunately, due to minor technical glitches, the round is declared semi-rated. It means that all rating changes must be divided by two.\nThere are two conditions though:\nFor each participant 𝑖, their modified rating change 𝑏𝑖 must be integer, and as close to 𝑎𝑖/2 as possible. It means that either 𝑏𝑖=⌊𝑎𝑖/2⌋ or 𝑏𝑖=⌈𝑎𝑖/2⌉. In particular, if 𝑎𝑖 is even, 𝑏𝑖=𝑎𝑖2. Here ⌊𝑥⌋ denotes rounding down to the largest integer not greater than 𝑥, and ⌈𝑥⌉ denotes rounding up to the smallest integer not smaller than 𝑥. The modified rating changes must be perfectly balanced — their sum must be equal to 0. Can you help with that?\nInput The first line contains a single integer 𝑛 (2≤𝑛≤13845), denoting the number of participants.\nEach of the next 𝑛 lines contains a single integer 𝑎𝑖 (−336≤𝑎𝑖≤1164), denoting the rating change of the 𝑖-th participant.\nThe sum of all 𝑎𝑖 is equal to 0.\nOutput Output 𝑛 integers 𝑏𝑖, each denoting the modified rating change of the 𝑖-th participant in order of input.\nFor any 𝑖, it must be true that either 𝑏𝑖=⌊𝑎𝑖/2⌋ or 𝑏𝑖=⌈𝑎𝑖/2⌉. The sum of all 𝑏𝑖 must be equal to 0.\nIf there are multiple solutions, print any. We can show that a solution exists for any valid input.\nExamples input\n3 10 -5 -5 output\n5 -2 -3 input\n7 -7 -29 0 3 24 -29 38 output\n-3 -15 0 2 12 -15 19 题解： 统计正数与负数的奇数之差，然后在输出时进行处理即可。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; int a[20010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int sum1 =0; int sum2 =0; for(int i = 0; i \u0026lt; n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); if(a[i] \u0026gt; 0 \u0026amp;\u0026amp; a[i] % 2 == 1) sum1++; if(a[i] \u0026lt; 0 \u0026amp;\u0026amp; a[i] % 2 == -1) sum2++; } if(sum1 \u0026lt; sum2){ sum1 = (sum2 - sum1) / 2; for(int i = 0; i \u0026lt; n; i++){ if(a[i] \u0026lt; 0 \u0026amp;\u0026amp; a[i]%2 == -1 \u0026amp;\u0026amp; sum1 \u0026gt; 0){ printf(\u0026#34;%d\\n\u0026#34;,a[i]/2 - 1); sum1--; } else { printf(\u0026#34;%d\\n\u0026#34;,a[i]/2); } } } else { sum1 = (sum1 - sum2) / 2; for(int i = 0; i \u0026lt; n; i++){ if(a[i] \u0026gt; 0 \u0026amp;\u0026amp; a[i]%2 == 1 \u0026amp;\u0026amp; sum1 \u0026gt; 0){ printf(\u0026#34;%d\\n\u0026#34;,a[i]/2 + 1); sum1--; } else { printf(\u0026#34;%d\\n\u0026#34;,a[i]/2); } } } return 0; } B： Balanced Tunnel 题目： Consider a tunnel on a one-way road. During a particular day, 𝑛 cars numbered from 1 to 𝑛 entered and exited the tunnel exactly once. All the cars passed through the tunnel at constant speeds.\nA traffic enforcement camera is mounted at the tunnel entrance. Another traffic enforcement camera is mounted at the tunnel exit. Perfectly balanced.\nThanks to the cameras, the order in which the cars entered and exited the tunnel is known. No two cars entered or exited at the same time.\nTraffic regulations prohibit overtaking inside the tunnel. If car 𝑖 overtakes any other car 𝑗 inside the tunnel, car 𝑖 must be fined. However, each car can be fined at most once.\nFormally, let\u0026rsquo;s say that car 𝑖 definitely overtook car 𝑗 if car 𝑖 entered the tunnel later than car 𝑗 and exited the tunnel earlier than car 𝑗. Then, car 𝑖 must be fined if and only if it definitely overtook at least one other car.\nFind the number of cars that must be fined.\nInput The first line contains a single integer 𝑛 (2≤𝑛≤105), denoting the number of cars.\nThe second line contains 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤𝑛), denoting the ids of cars in order of entering the tunnel. All 𝑎𝑖 are pairwise distinct.\nThe third line contains 𝑛 integers 𝑏1,𝑏2,…,𝑏𝑛 (1≤𝑏𝑖≤𝑛), denoting the ids of cars in order of exiting the tunnel. All 𝑏𝑖 are pairwise distinct.\nOutput Output the number of cars to be fined.\nExamples input\n5 3 5 2 1 4 4 3 2 5 1 output\n2 input\n7 5 2 3 6 7 1 4 2 3 6 7 1 4 5 output\n6 input\n2 1 2 1 2 output\n0 题解： 此代码用的归并排序进行处理，复杂度为nlogn 有复杂度为n的方法，以后补上。进行归并排布时，出现逆序时，将偏大的数字进行记录就可。\n代码: #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; int p[100010]; int t[100010]; int a[100010]; int used[100010]; int sum=0; void solve(int l,int r) { //printf(\u0026#34;%d %d\\n\u0026#34;,l,r); if(r-l\u0026lt;2) { if(r-l == 1 \u0026amp;\u0026amp; a[l] \u0026gt; a[r]){ if(!used[a[l]]){ // printf(\u0026#34;%d %d\\n\u0026#34;,a[l],a[r]); used[a[l]] = 1; // printf(\u0026#34;2 used %d = true\\n\u0026#34;,a[l]); sum++; } swap(a[l], a[r]); } return ; } int m = (l + r) \u0026gt;\u0026gt; 1; solve(l , m); solve(m+1 , r); int now = m-l+1; int sz = l, sy = m+1; /* for(int i = l; i \u0026lt;= r;i++) printf(\u0026#34;%d \u0026#34;, a[i]); printf(\u0026#34;\\n%d\\n\u0026#34;,used[6]); printf(\u0026#34;\\n\u0026#34;);*/ for(int i = 0; i \u0026lt; r - l + 1; i++) { // printf(\u0026#34; i:%d used %d %d\\n\u0026#34;,i,a[sz],used[a[sz]]); if(sz \u0026lt;= m \u0026amp;\u0026amp; sy \u0026lt;= r) { if(a[sz] \u0026gt; a[sy]){ t[i] = a[sy]; sy++; if(!used[a[sz]]){ //printf(\u0026#34;%d %d\\n\u0026#34;,a[sz],a[sy-1]); sum++; used[a[sz]] = 1; // printf(\u0026#34;used %d %d\\n\u0026#34;,a[sz],used[a[sz]]); // printf(\u0026#34;sy r %d %d\\n\u0026#34;, sy,r); } } else { t[i] = a[sz]; if(sy != m + 1 \u0026amp;\u0026amp; !used[a[sz]]) { sum++; used[a[sz]] = 1; } sz++; now--; } } else if(sz == m+1) { while(sy \u0026lt;= r) { t[i] = a[sy]; sy++; i++; } } else { // printf(\u0026#34;sz %d\\n\u0026#34;,a[sz]); // printf(\u0026#34;used %d %d \\n\u0026#34;,a[sz],used[a[sz]]); while(sz \u0026lt;= m) { t[i] = a[sz]; // printf(\u0026#34;sz %d\\n\u0026#34;,a[sz]); // printf(\u0026#34;used %d %d \\n\u0026#34;,a[sz],used[a[sz]]); if(used[a[sz]] == 0){ sum++; used[a[sz]] = 1; } sz++; i++; } } } for(int i= l ; i \u0026lt;= r; i++) a[i] = t[i-l]; } int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 1; i \u0026lt;= n; i++){ int now ; scanf(\u0026#34;%d\u0026#34;, \u0026amp;now); p[now] = i; } for(int i = 1; i \u0026lt;= n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); a[i] = p[a[i]]; } solve(1,n); printf(\u0026#34;%d\\n\u0026#34;, sum); return 0; } C：Balanced Removals (Easier) 题目： This is an easier version of the problem. In this version, 𝑛≤2000.\nThere are 𝑛 distinct points in three-dimensional space numbered from 1 to 𝑛. The 𝑖-th point has coordinates (𝑥𝑖,𝑦𝑖,𝑧𝑖). The number of points 𝑛 is even.\nYou\u0026rsquo;d like to remove all 𝑛 points using a sequence of 𝑛2 snaps. In one snap, you can remove any two points 𝑎 and 𝑏 that have not been removed yet and form a perfectly balanced pair. A pair of points 𝑎 and 𝑏 is perfectly balanced if no other point 𝑐 (that has not been removed yet) lies within the axis-aligned minimum bounding box of points 𝑎 and 𝑏.\nFormally, point 𝑐 lies within the axis-aligned minimum bounding box of points 𝑎 and 𝑏 if and only if min(𝑥𝑎,𝑥𝑏)≤𝑥𝑐≤max(𝑥𝑎,𝑥𝑏), min(𝑦𝑎,𝑦𝑏)≤𝑦𝑐≤max(𝑦𝑎,𝑦𝑏), and min(𝑧𝑎,𝑧𝑏)≤𝑧𝑐≤max(𝑧𝑎,𝑧𝑏). Note that the bounding box might be degenerate.\nFind a way to remove all points in 𝑛2 snaps.\nInput The first line contains a single integer 𝑛 (2≤𝑛≤2000; 𝑛 is even), denoting the number of points.\nEach of the next 𝑛 lines contains three integers 𝑥𝑖, 𝑦𝑖, 𝑧𝑖 (−108≤𝑥𝑖,𝑦𝑖,𝑧𝑖≤108), denoting the coordinates of the 𝑖-th point.\nNo two points coincide.\nOutput Output 𝑛2 pairs of integers 𝑎𝑖,𝑏𝑖 (1≤𝑎𝑖,𝑏𝑖≤𝑛), denoting the indices of points removed on snap 𝑖. Every integer between 1 and 𝑛, inclusive, must appear in your output exactly once.\nWe can show that it is always possible to remove all points. If there are many solutions, output any of them.\nExamples input\n6 3 1 0 0 3 0 2 2 0 1 0 0 1 3 0 0 1 0 output\n3 6 5 1 2 4 input\n8 0 1 1 1 0 1 1 1 0 1 1 1 2 2 2 3 2 2 2 3 2 2 2 3 output\n4 5 1 6 2 7 3 8 题解： 按线面体的顺序进行依次删除。即按xyz顺序进行排序，先删除xy相同的，再删除x相同的，然后再依次删除，注意每次删除后都要排序一次。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; struct point{ int x,y,z; int index; }; point p[2010]; point tmp[2010]; bool cmp(point a, point b){ if(a.x != b.x){ return a.x \u0026lt; b.x; } else if(a.y != b.y){ return a.y \u0026lt; b.y; } else{ return a.z \u0026lt; b.z; } } bool used[2010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 1; i \u0026lt;= n; i++){ scanf(\u0026#34;%d%d%d\u0026#34;,\u0026amp;p[i].x, \u0026amp;p[i].y, \u0026amp;p[i].z); p[i].index = i; } sort(p + 1, p + n + 1, cmp); for(int i = 2 ; i \u0026lt;= n; i++) { if(p[i].x == p[i - 1].x \u0026amp;\u0026amp; p[i].y == p[i - 1].y){ printf(\u0026#34;%d %d\\n\u0026#34;,p[i].index, p[i - 1].index); used[p[i].index] = used[p[i - 1].index] = true; i++; } } int now = 1; for(int i = 1; i \u0026lt;= n; i++) { if(!used[p[i].index]) tmp[now++] = p[i]; } now--; for(int i = 1; i \u0026lt;= now; i++) p[i] = tmp[i]; sort(p + 1, p + 1 + now,cmp); // printf(\u0026#34;now %d\\n\u0026#34;,now); for(int i = 2 ; i \u0026lt;= now; i++) { if(p[i].x == p[i - 1].x){ printf(\u0026#34;%d %d\\n\u0026#34;,p[i].index, p[i - 1].index); used[p[i].index] = used[p[i - 1].index] = true; i++; } } int o = 1; for(int i = 1; i \u0026lt;= now; i++) { if(!used[p[i].index]) tmp[o++] = p[i]; } o--; sort(tmp + 1, tmp + 1 + o,cmp); //printf(\u0026#34;o %d\\n\u0026#34;,o); for(int i = 1; i \u0026lt;= o; i++){ printf(\u0026#34;%d %d\\n\u0026#34;,tmp[i].index,tmp[i + 1].index); i++; } return 0; } ","permalink":"https://eonh1u.github.io/posts/cf-global-round-5/","summary":"\u003ch1 id=\"abalanced-rating-changes\"\u003eA:Balanced Rating Changes\u003c/h1\u003e\n\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eAnother Codeforces Round has just finished! It has gathered 𝑛 participants, and according to the results, the expected rating change of participant 𝑖 is 𝑎𝑖. These rating changes are perfectly balanced — their sum is equal to 0.\u003c/p\u003e\n\u003cp\u003eUnfortunately, due to minor technical glitches, the round is declared semi-rated. It means that all rating changes must be divided by two.\u003c/p\u003e\n\u003cp\u003eThere are two conditions though:\u003c/p\u003e","title":"cf-Global Round 5"},{"content":"题目： 小Y上数据结构课的时候摸鱼，听到老师在讲用栈做括号匹配，于是乎边随意写了一个合法的括号序列。但是光是写括号太无聊了，他现在想知道这个括号序列的价值。他是这样定义一个括号序列的价值的：\n1、一对括号价值一分（比如\u0026quot;()\u0026ldquo;得一分）\n2、两个合法的括号序列的拼接而成的括号序列的价值是他们的价值的和（比如\u0026rdquo;()()\u0026ldquo;价值为1+1=2）\n3、嵌套的括号的序列的价值是，所嵌套的括号序列的价值的翻倍（比如\u0026rdquo;((()))\u0026ldquo;价值为1*2*2=4）\n下课了，qz看到小Y写的括号序列，他一眼就推测出了规则并得到了括号序列的价值。那么问题来了，小Y写下的括号序列的价值是多少呢？\n输入 一个只包含\u0026rsquo;(\u0026lsquo;和\u0026rsquo;)\u0026lsquo;的合法的括号序列S，代表小Y写下的括号序列，一个合法的括号序列是这样定义的: 1、（）是合法的括号序列 2、若字符串A和B是合法的括号序列，那么AB也是合法的括号序列 3、若字符串A是合法的括号序列，那么(A)也是合法的括号序列\n2\u0026lt;= |S| \u0026lt;=50\n输出 一个字符串S，代表小Y所写的括号序列\n输入样例 (()(())) 输出样例 6 题解： 用栈进行处理，对‘(’加一个num属性，记录当‘(\u0026lsquo;出栈时所增加的值，如果当一\u0026rsquo;(\u0026lsquo;出栈时，栈不为空，则将此位置的num加至最近的字符。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;stack\u0026gt; #include\u0026lt;string.h\u0026gt; using namespace std; char s[55]; struct point{ char c; int num; }; point p[55]; stack\u0026lt;point\u0026gt; sta; int main() { scanf(\u0026#34;%s\u0026#34;, s); int len = strlen(s); int ans = 0; for(int i = 0; i \u0026lt; len; i++){ if(s[i] == \u0026#39;(\u0026#39;){ point a; a.c = \u0026#39;(\u0026#39;; a.num = 0; sta.push(a); } else{ point now = sta.top(); sta.pop(); if(sta.empty()){ if(now.num == 0) now.num = 1; ans += now.num; } else{ point a = sta.top(); sta.pop(); if(now.num == 0) a.num += 2; else{ a.num += now.num*2; } sta.push(a); } } } printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2594-%E6%8B%AC%E5%8F%B7%E4%B9%8B%E4%BB%B7/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小Y上数据结构课的时候摸鱼，听到老师在讲用栈做括号匹配，于是乎边随意写了一个合法的括号序列。但是光是写括号太无聊了，他现在想知道这个括号序列的价值。他是这样定义一个括号序列的价值的：\u003c/p\u003e\n\u003cp\u003e1、一对括号价值一分（比如\u0026quot;()\u0026ldquo;得一分）\u003c/p\u003e\n\u003cp\u003e2、两个合法的括号序列的拼接而成的括号序列的价值是他们的价值的和（比如\u0026rdquo;()()\u0026ldquo;价值为1+1=2）\u003c/p\u003e\n\u003cp\u003e3、嵌套的括号的序列的价值是，所嵌套的括号序列的价值的翻倍（比如\u0026rdquo;((()))\u0026ldquo;价值为1*2*2=4）\u003c/p\u003e\n\u003cp\u003e下课了，qz看到小Y写的括号序列，他一眼就推测出了规则并得到了括号序列的价值。那么问题来了，小Y写下的括号序列的价值是多少呢？\u003c/p\u003e","title":"51nod-2594-括号之价"},{"content":"题目： 现在有 𝑛 个位置 1\u0026hellip;𝑛 。\n给𝑞个区间，请你选出选𝑞−2个，使得覆盖位置个数最大。\n输入 第一行两个数n,q(3\u0026lt;=n,q\u0026lt;=5000)。 接下来q行，其中第i行两个数l[i],r[i]，表示第i个区间能覆盖所有满足l[i]\u0026lt;=x\u0026lt;=r[i]的位置x。\n输出 一个数表示最大值。\n输入样例 4 3 1 1 2 2 3 4 输出样例 2 题解： 暴力即可\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; using namespace std; struct point{ int l,r; }; point p[5010]; int sum[5010]; int main() { int n,q; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;n, \u0026amp;q); for(int i = 0; i \u0026lt; q; i++) scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;p[i].l, \u0026amp;p[i].r); int now = 0; for(int i = 0; i \u0026lt; q; i++) for(int j = p[i].l; j \u0026lt;= p[i].r; j++){ if(sum[j] == 0) now++; sum[j]++; } int MIN = 99999; int o = 0; for(int i = 0; i \u0026lt; q; i++){ int s = 0; for(int j = p[i].l; j \u0026lt;= p[i].r; j++){ sum[j]--; if(sum[j] == 0) s++; } if(s \u0026lt; MIN) o = i; MIN = min(MIN,s); for(int j = p[i].l; j \u0026lt;= p[i].r; j++){ sum[j]++; } } now -= MIN; MIN = 9999; for(int i = p[o].l; i \u0026lt;= p[o].r; i++) sum[i]--; for(int i = 0; i \u0026lt; q; i++){ if(i == o) continue; int s = 0; for(int j = p[i].l; j \u0026lt;= p[i].r; j++){ sum[j]--; if(sum[j] == 0) s++; } MIN = min(MIN,s); for(int j = p[i].l; j \u0026lt;= p[i].r; j++){ sum[j]++; } } printf(\u0026#34;%d\u0026#34;, now - MIN); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2531-%E6%9C%80%E5%A4%A7%E8%A6%86%E7%9B%96/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e现在有 𝑛 个位置 1\u0026hellip;𝑛 。\u003c/p\u003e\n\u003cp\u003e给𝑞个区间，请你选出选𝑞−2个，使得覆盖位置个数最大。\u003c/p\u003e\n\u003ch2 id=\"输入\"\u003e输入\u003c/h2\u003e\n\u003cp\u003e第一行两个数n,q(3\u0026lt;=n,q\u0026lt;=5000)。\n接下来q行，其中第i行两个数l[i],r[i]，表示第i个区间能覆盖所有满足l[i]\u0026lt;=x\u0026lt;=r[i]的位置x。\u003c/p\u003e","title":"51nod-2531-最大覆盖"},{"content":"题目： b有一个n*m的矩阵A，矩阵的每个元素为一个字符，现在她希望删除其中的一些列，使得剩下的列在每一行形成的字符串的字典序不降。\n即对于第i行，将剩下的列上的字符顺序拼接，形成一个字符串，字符串记作a[i]。要求a[i]\u0026lt;=a[i+1](i=1..n-1)。\n请问小b最少要删多少列。\n如A = {\u0026ldquo;abcdef\u0026rdquo;, \u0026ldquo;uvwxyz\u0026rdquo;}，删除的列为第1,3,4列，删除后 A 为 {\u0026ldquo;bef\u0026rdquo;, \u0026ldquo;vyz\u0026rdquo;}，且 \u0026ldquo;bef\u0026rdquo; \u0026lt;= \u0026ldquo;vyz\u0026rdquo;\n样例解释：\n删掉第一列，剩下的是\u0026quot;a\u0026quot; \u0026ldquo;b\u0026rdquo; \u0026ldquo;c\u0026rdquo;，\u0026ldquo;a\u0026rdquo; \u0026lt;= \u0026ldquo;b\u0026rdquo; \u0026lt;= \u0026ldquo;c\u0026rdquo;，满足条件。\n输入 第一行输入一个正整数n，表示矩阵A的行数； 之后n行每行输入一个字符串，其长度相等； 1≤n,m≤100。\n输出 输出一个非负整数，表示删掉的列数\n输入样例 3 ca bb ac 输出样例 1 题解： 首先看第一列是否有降序字符，如果有，则第一列删除，否则，看时候有相同字符的行，记录这些有相同字符行的位置，再进行下一列的判断时，只判断每个相同字符的行即可。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; char a[110][110]; vector\u0026lt;int\u0026gt; s[26]; vector\u0026lt;int\u0026gt; tmp[26]; bool isR() { for(int i = 0; i \u0026lt; 26; i++){ if(s[i].size() \u0026gt; 1) return true; } return false; } int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%s\u0026#34;, a[i]); int m = strlen(a[0]); for(int i = 0; i \u0026lt; n; i++) s[0].push_back(i); int ans = 0; int p = 0; //printf(\u0026#34;m %d\\n\u0026#34;,m); // for(int i = 0; i \u0026lt; n; i++) // printf(\u0026#34;%s\\n\u0026#34;, a[i]); // for(int i = 0; i \u0026lt; 26; i++) // printf(\u0026#34;%d:%d\\n\u0026#34;, i,s[i].size()); while(isR() \u0026amp;\u0026amp; p \u0026lt; m){ //printf(\u0026#34;p %d\\n\u0026#34;, p); bool flag = true; for(int i = 0; i \u0026lt; 26; i++){ if(s[i].size() \u0026gt; 1){ int l = s[i].size(); for(int j = 1; j \u0026lt; l; j++){ if(a[s[i][j]][p] \u0026lt; a[s[i][j - 1]][p]){ flag = false; break; } } } if(!flag) break; } if(flag == false){ ans++; // printf(\u0026#34;ans : %d\\n\u0026#34;, ans); } else{ for(int i = 0; i \u0026lt; 26; i++){ if(s[i].size() \u0026gt; 1){ int l = s[i].size(); // printf(\u0026#34;l %d\\n\u0026#34;, l); for(int j = 1; j \u0026lt; l; j++){ if(a[s[i][j]][p] == a[s[i][j - 1]][p]){ tmp[a[s[i][j]][p] - \u0026#39;a\u0026#39;].push_back(s[i][j - 1]); while(j\u0026lt; l \u0026amp;\u0026amp; a[s[i][j]][p] == a[s[i][j - 1]][p]){ tmp[a[s[i][j]][p] - \u0026#39;a\u0026#39;].push_back(s[i][j]); j++; } } } } } for(int i = 0; i \u0026lt; 26;i++){ s[i] = tmp[i]; tmp[i].clear(); } //for(int i = 0; i \u0026lt; 26; i++) // printf(\u0026#34;%d:%d\\n\u0026#34;, i,s[i].size()); } p++; } printf(\u0026#34;%d\u0026#34;,ans); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2523-%E5%B0%8Fb%E5%88%A0%E5%88%97/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003eb有一个n*m的矩阵A，矩阵的每个元素为一个字符，现在她希望删除其中的一些列，使得剩下的列在每一行形成的字符串的字典序不降。\u003c/p\u003e\n\u003cp\u003e即对于第i行，将剩下的列上的字符顺序拼接，形成一个字符串，字符串记作a[i]。要求a[i]\u0026lt;=a[i+1](i=1..n-1)。\u003c/p\u003e\n\u003cp\u003e请问小b最少要删多少列。\u003c/p\u003e\n\u003cp\u003e如A = {\u0026ldquo;abcdef\u0026rdquo;, \u0026ldquo;uvwxyz\u0026rdquo;}，删除的列为第1,3,4列，删除后 A 为 {\u0026ldquo;bef\u0026rdquo;, \u0026ldquo;vyz\u0026rdquo;}，且 \u0026ldquo;bef\u0026rdquo; \u0026lt;= \u0026ldquo;vyz\u0026rdquo;\u003c/p\u003e\n\u003cp\u003e样例解释：\u003c/p\u003e\n\u003cp\u003e删掉第一列，剩下的是\u0026quot;a\u0026quot; \u0026ldquo;b\u0026rdquo; \u0026ldquo;c\u0026rdquo;，\u0026ldquo;a\u0026rdquo; \u0026lt;= \u0026ldquo;b\u0026rdquo; \u0026lt;= \u0026ldquo;c\u0026rdquo;，满足条件。\u003c/p\u003e","title":"51nod-2523-小b删列"},{"content":"题目： 小b喜欢和为K的倍数的序列。\n现在有一个长度为n的序列A，请问A有多少个非空连续子序列是小b喜欢的。\n输入 第一行输入一个正整数n； 第二行输入n个整数，表示A[i]，以空格隔开； 第三行输入一个正整数K； 其中1≤n≤30000，对于任意A[i]有-10000≤A[i]≤10000，2≤K≤10000\n输出 输出一个数，表示子序列的数目\n输入样例 6 4 5 0 -2 -3 1 5 输出样例 7 题解： 暴力即可，注意要将数据范围控制在k内，%k即可。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int a[30010]; int sum[30010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 1; i \u0026lt;= n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); } int k; int ans = 0; scanf(\u0026#34;%d\u0026#34;, \u0026amp;k); for(int i = 1; i \u0026lt;= n; i++){ sum[i] = (sum[i - 1] + a[i]) % k; } for(int i = 0; i \u0026lt;= n; i++) for(int j = i + 1; j \u0026lt;= n; j++){ if((sum[j] - sum[i]) % k == 0) ans++; } printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2522-%E5%92%8C%E4%B8%BAk%E7%9A%84%E5%80%8D%E6%95%B0/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小b喜欢和为K的倍数的序列。\u003c/p\u003e\n\u003cp\u003e现在有一个长度为n的序列A，请问A有多少个非空连续子序列是小b喜欢的。\u003c/p\u003e\n\u003ch2 id=\"输入\"\u003e输入\u003c/h2\u003e\n\u003cp\u003e第一行输入一个正整数n；\n第二行输入n个整数，表示A[i]，以空格隔开；\n第三行输入一个正整数K；\n其中1≤n≤30000，对于任意A[i]有-10000≤A[i]≤10000，2≤K≤10000\u003c/p\u003e\n\u003ch2 id=\"输出\"\u003e输出\u003c/h2\u003e\n\u003cp\u003e输出一个数，表示子序列的数目\u003c/p\u003e","title":"51nod-2522-和为k的倍数"},{"content":"题目： 有两个长度为n的序列A,B，你需要重排列A，使得满足A[i]\u0026gt;B[i]的i的数目尽量大。 只需输出这个最大个数即可。\n输入 第一行输入一个正整数n； 第二、三行分别输出n个非负整数，表示A、B中的元素，以空格隔开； 其中1≤n≤10000，0≤A[i],B[i]≤10^9。\n输出 输出一行一个数，表示最大个数\n输入样例 4 2 7 11 15 1 10 4 11\n输出样例 4\n题解： 田忌赛马。将两个数组排序，对于b数组中b[i]，从a中找到第一个大于b[i]的即可（排序后，ab数组都为升序）。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; using namespace std; int a[10010],b[10010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;b[i]); sort(a, a + n); sort(b, b + n); int ans = 0; int now = 0; for(int i = 0; i \u0026lt; n; i++){ while(a[now] \u0026lt;= b[i] \u0026amp;\u0026amp; now \u0026lt; n){ now++; } if(now == n){ break; } ans++; now++; } printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2513-%E9%87%8D%E6%8E%92%E5%88%97/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e有两个长度为n的序列A,B，你需要重排列A，使得满足A[i]\u0026gt;B[i]的i的数目尽量大。\n只需输出这个最大个数即可。\u003c/p\u003e\n\u003ch2 id=\"输入\"\u003e输入\u003c/h2\u003e\n\u003cp\u003e第一行输入一个正整数n；\n第二、三行分别输出n个非负整数，表示A、B中的元素，以空格隔开；\n其中1≤n≤10000，0≤A[i],B[i]≤10^9。\u003c/p\u003e\n\u003ch2 id=\"输出\"\u003e输出\u003c/h2\u003e\n\u003cp\u003e输出一行一个数，表示最大个数\u003c/p\u003e","title":"51nod-2513-重排列"},{"content":"题目： 小b有一个数n，现在她想把n的每一位重排列，使得得到的结果为2的幂次。\n请问小b能得到2的幂次吗？\n注意重排列后不允许有前导0。\n样例解释：46重排列成64，为2^6。\n输入 输入一个数N，其中1≤N≤10^9\n输出 满足条件，输出“true”； 不满足，则输出“false”。\n输入样例 46 输出样例 true 题解： 当n的数字个数与某2的次幂数字个数相同时，比较各个数字出现的次数，如果相同则为true\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; using namespace std; int b[10]; int a[10]; int len(int n){ int l = 0; while(n){ l++; n /= 10; } return l; } bool cmp(){ for(int i = 0; i \u0026lt; 10; i++){ if(a[i] != b[i]) return false; } return true; } int mi(int m){ int now = 1; for(int i = 0; i \u0026lt; m; i++) now *= 2; return now; } void get(int p){ for(int i = 0; i \u0026lt; 10; i++) b[i] = 0; while(p){ b[p%10]++; p /= 10; } } int main() { int n; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); bool flag = false; int i = 0; int p = n; while(p){ a[p%10]++; p /= 10; } while(1){ if(len(mi(i)) == len(n)){ get(mi(i)); if(cmp()){ flag = true; break; } } if(len(mi(i)) \u0026gt; len(n)) break; i++; } if(flag) printf(\u0026#34;true\u0026#34;); else { printf(\u0026#34;false\u0026#34;); } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2512-%E9%87%8D%E6%8E%92%E5%88%97%E5%BE%97%E5%88%B02%E7%9A%84%E5%B9%82/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小b有一个数n，现在她想把n的每一位重排列，使得得到的结果为2的幂次。\u003c/p\u003e\n\u003cp\u003e请问小b能得到2的幂次吗？\u003c/p\u003e\n\u003cp\u003e注意重排列后不允许有前导0。\u003c/p\u003e\n\u003cp\u003e样例解释：46重排列成64，为2^6。\u003c/p\u003e\n\u003ch2 id=\"输入\"\u003e输入\u003c/h2\u003e\n\u003cp\u003e输入一个数N，其中1≤N≤10^9\u003c/p\u003e\n\u003ch2 id=\"输出\"\u003e输出\u003c/h2\u003e\n\u003cp\u003e满足条件，输出“true”；\n不满足，则输出“false”。\u003c/p\u003e","title":"51nod-2512-重排列得到2的幂"},{"content":"题目： 小b有n张牌。\n现在她想把牌分组，使得每组都是长度为W的顺子，即由连续W个数组成。\n请问小b能做到吗？\n输入 第一行输入一个数n，表示手牌张数； 第二行输入n个非负整数，表示每张牌的数字，以空格隔开； 第三行输入一个数，表示每组大小W； 其中1≤W≤n≤10000，任意牌的数字hand[i]满足0≤hand[i]≤10^9\n输出 可以分组，输出“true”； 不能分组，输出“false”。\n输入样例 9 1 2 3 6 2 3 4 7 8 3 输出样例 true 解法 用map记录出现的数，每次取剩下的最小的数，然后删除相应的连续的数，当出现为负数的时候，则为false\n代码 #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; map\u0026lt;int,int\u0026gt; m; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int MAX = 0; for(int i = 0; i \u0026lt; n; i++){ int a; scanf(\u0026#34;%d\u0026#34;, \u0026amp;a); MAX = max(a,MAX); m[a]++; } int q; scanf(\u0026#34;%d\u0026#34;, \u0026amp;q); if(n%q != 0){ printf(\u0026#34;false\u0026#34;); return 0; } map\u0026lt;int,int\u0026gt; ::iterator it; while(n){ /*for(it = m.begin(); it != m.end(); it++){ printf(\u0026#34;%d %d\\n\u0026#34;, it-\u0026gt;first, it-\u0026gt;second); } printf(\u0026#34;\\n\\n\u0026#34;);*/ int p_1 = m.begin()-\u0026gt;first; int p_2 = m.begin()-\u0026gt;second; if(p_1 + q - 1 \u0026gt; MAX){ printf(\u0026#34;false\u0026#34;); return 0; } for(int i = 1; i \u0026lt; q; i++){ if(m.find(i+p_1) == m.end()){ printf(\u0026#34;false\u0026#34;); return 0; } m[i+p_1] -= p_2; if(m[i+p_1] \u0026lt; 0){ printf(\u0026#34;false\u0026#34;); return 0; } if(m[i + p_1] == 0){ //pair\u0026lt;int,int\u0026gt; a(i+p_1,0); m.erase(i+p_1); } } m.erase(p_1); n -= p_2 * q; } printf(\u0026#34;true\u0026#34;); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2510-%E9%A1%BA%E5%AD%90/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小b有n张牌。\u003c/p\u003e\n\u003cp\u003e现在她想把牌分组，使得每组都是长度为W的顺子，即由连续W个数组成。\u003c/p\u003e\n\u003cp\u003e请问小b能做到吗？\u003c/p\u003e","title":"51nod-2510-顺子"},{"content":"题目： 小b有一个长度为n的序列t，现在她对于每个i，求最小的正数j满足𝑖+𝑗≤𝑛且𝑡𝑖+𝑗\u0026gt;𝑡𝑖，输出j，如果不存在这样的j，则输出0。\n样例解释：\n对于i=1，𝑡2\u0026gt;𝑡1，所以最小的j=1；\n对于i=7，不存在这样的j，所以输出0。\n输入 第一行输入一个数n； 第二行输入n个数t1-tn，以空格隔开； 其中1≤n≤30000，对于任意ti满足30≤ti≤100.\n输出 输出一行n个数，第i个数表示i的答案。\n输入样例 8 73 74 75 71 69 72 76 73 输出样例 1 1 4 2 1 1 0 0 解法： 用set记录ti出现的位置下标，在处理每个ti时，在大于ti的数中找到下标大于i并且i+j\u0026lt;n的最小值。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;set\u0026gt; using namespace std; set\u0026lt;int\u0026gt; s[110]; int a[30010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 1; i \u0026lt;= n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); s[a[i]].insert(i); } for(int i = 1; i \u0026lt;= n; i++){ bool flag = false; int ans = 30010; for(int j = a[i] + 1; j \u0026lt;= 100; j++){ if(s[j].upper_bound(i) != s[j].end()){ int p = *s[j].upper_bound(i); //printf(\u0026#34;%d\\n\u0026#34;,p); flag = true; ans = min(ans,p - i); } } if(!flag) printf(\u0026#34;0 \u0026#34;); else printf(\u0026#34;%d \u0026#34;,ans); } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2500-%E5%90%8E%E9%9D%A2%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%A4%A7%E4%BA%8E/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小b有一个长度为n的序列t，现在她对于每个i，求最小的正数j满足𝑖+𝑗≤𝑛且𝑡𝑖+𝑗\u0026gt;𝑡𝑖，输出j，如果不存在这样的j，则输出0。\u003c/p\u003e\n\u003cp\u003e样例解释：\u003c/p\u003e\n\u003cp\u003e对于i=1，𝑡2\u0026gt;𝑡1，所以最小的j=1；\u003c/p\u003e\n\u003cp\u003e对于i=7，不存在这样的j，所以输出0。\u003c/p\u003e","title":"51nod-2500-后面第一个大于"},{"content":"题目： 小b有一个非负整数N，她想请你找出 ≤𝑁 的最大整数x，满足x各个位数上的数字是不降的。也就是说，设x的十进制表示为 𝑎1,𝑎2,…,𝑎𝑚，则对于任意 1≤𝑖\u0026lt;𝑚，𝑎𝑖≤𝑎𝑖+1。\n输入 输入一个非负整数N。 0≤N≤10^9\n输出 输出一个整数，表示答案\n输入样例 332 输出样例 299 解法： 记录出现降序的位置，然后反向处理，找到一个可以减1的位置，然后后面的部分全部置为9，注意处理前部分全部是1开头的情况。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int num[30]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int s = n; int len = 0; while(n){ num[len++] = n%10; n /= 10; } int p = 0; for(int i = len - 1; i \u0026gt; 0; i--){ if(num[i] \u0026gt; num[i - 1]){ p = i; break; } } if(p == 0){ printf(\u0026#34;%d\\n\u0026#34;, s); } else{ int i = p; while(num[i] - 1 \u0026lt; num[i + 1] \u0026amp;\u0026amp; i \u0026lt; len - 1) i++; if(i == len - 1){ if(num[i] == 1){ for(int j = 0; j \u0026lt; len - 1; j++) printf(\u0026#34;9\u0026#34;); } else{ printf(\u0026#34;%d\u0026#34;,num[i] - 1); for(int j = 0; j \u0026lt; len - 1; j++) printf(\u0026#34;9\u0026#34;); } } else{ for(int j = len - 1; j \u0026gt; p; j--) printf(\u0026#34;%d\u0026#34;, num[j]); printf(\u0026#34;%d\u0026#34;, num[p] - 1); for(int j = p - 1; j \u0026gt;= 0; j--) printf(\u0026#34;9\u0026#34;); } } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2499-%E4%B8%8D%E9%99%8D%E7%9A%84%E6%95%B0%E5%AD%97/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小b有一个非负整数N，她想请你找出 ≤𝑁 的最大整数x，满足x各个位数上的数字是不降的。也就是说，设x的十进制表示为 𝑎1,𝑎2,…,𝑎𝑚，则对于任意 1≤𝑖\u0026lt;𝑚，𝑎𝑖≤𝑎𝑖+1。\u003c/p\u003e","title":"51nod-2499-不降的数字"},{"content":"题目： 小b有一个01序列，她想找到一个最长的区间使得这个区间的01能两两配对，即0的个数和1的个数相等。求最长区间的长度。\n输入 第一行一个正整数n，表示数组长度，其中0＜n≤50000； 第二行n个0或1，以空格隔开。\n输出 输出一个数，表示最长区间的长度\n输入样例 3 0 1 0 输出样例 2 解法： 将0当做-1处理，处理前缀和，记录前缀和相同的位置，计算出前缀和相同位置的最长距离。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;vector\u0026gt; #include\u0026lt;cstring\u0026gt; using namespace std; int a[1000010]; vector\u0026lt;int\u0026gt; p[2000010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); for(int i = 1; i \u0026lt;=n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); int sum = 0; int Max = -999999999; int Min = 999999999; p[1000000].push_back(0); for(int i = 1; i \u0026lt;= n; i++) { if(a[i] == 0) sum++; else sum--; Max = max(sum, Max); Min = min(sum, Min); p[sum + 1000000].push_back(i); } int ans = 0; //printf(\u0026#34;%d %d\\n\u0026#34;, Min, Max); for(int i = Min + 1000000; i \u0026lt;= Max + 1000000; i++) { ans = max(p[i][p[i].size() - 1]-p[i][0], ans); } printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2494-%E6%9C%80%E9%95%BF%E9%85%8D%E5%AF%B9/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小b有一个01序列，她想找到一个最长的区间使得这个区间的01能两两配对，即0的个数和1的个数相等。求最长区间的长度。\u003c/p\u003e\n\u003ch2 id=\"输入\"\u003e输入\u003c/h2\u003e\n\u003cp\u003e第一行一个正整数n，表示数组长度，其中0＜n≤50000；\n第二行n个0或1，以空格隔开。\u003c/p\u003e\n\u003ch2 id=\"输出\"\u003e输出\u003c/h2\u003e\n\u003cp\u003e输出一个数，表示最长区间的长度\u003c/p\u003e","title":"51nod-2494-最长配对"},{"content":"题目： 小b有两个长度都为n的序列A,B。\n现在她需要选择一些i，然后交换A[i]和B[i]，使得A和B都变成严格递增的序列。\n你能帮小b求出最少交换次数吗？\n输入保证有解。\n输入 第一行输入一个正整数n，表示两个数组的长度； 第二行输入n个数，表示A[i]，以空格隔开； 第三行输入n个数，表示B[i]，以空格隔开； 其中1≤n≤1000, 0≤A[i],B[i]≤2000\n输出 输出一个数，表示交换次数\n输入样例 4 1 3 5 4 1 2 3 7 输出样例 1 解法： dp,dp[i][0]代表处理到i时，不进行改变使得满足要求的最少交换次数，dp[i][1]代表交换使得满足要求的最少交换次数。进行状态转移时，进行a,b数组的比较，选最小值(具体看代码)\n代码: #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; using namespace std; int dp[1010][2]; int a[1010],b[1010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;b[i]); dp[0][1] = 1; for(int i = 1; i \u0026lt; n; i++){ dp[i][0] = dp[i][1] = 99999; } for(int i = 1; i \u0026lt; n; i++) { if(a[i] \u0026gt; a[i - 1] \u0026amp;\u0026amp; b[i] \u0026gt; b[i - 1]){ dp[i][0] = min(dp[i][0],dp[i - 1][0]); dp[i][1] = min(dp[i][1],dp[i - 1][1] + 1); } if(a[i] \u0026gt; b[i - 1] \u0026amp;\u0026amp; b[i] \u0026gt; a[i - 1]){ dp[i][0] = min(dp[i][0],dp[i - 1][1]); dp[i][1] = min(dp[i][1],dp[i - 1][0] + 1); } } printf(\u0026#34;%d\\n\u0026#34;, min(dp[n - 1][0], dp[n - 1][1])); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2484-%E5%B0%8Fb%E5%92%8C%E6%8E%92%E5%BA%8F/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e小b有两个长度都为n的序列A,B。\u003c/p\u003e\n\u003cp\u003e现在她需要选择一些i，然后交换A[i]和B[i]，使得A和B都变成严格递增的序列。\u003c/p\u003e\n\u003cp\u003e你能帮小b求出最少交换次数吗？\u003c/p\u003e\n\u003cp\u003e输入保证有解。\u003c/p\u003e","title":"51nod-2484-小b和排序"},{"content":"题目： 春春是一名道路工程师，负责铺设一条长度为 n 的道路。\n铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n 块首尾相连的区域，一开始，第 i 块区域下陷的深度为 𝑑𝑖 。\n春春每天可以选择一段连续区间[L,R] ，填充这段区间中的每块区域，让其下陷深度减少 1。在选择区间时，需要保证，区间内的每块区域在填充前下陷深度均不为 0 。\n春春希望你能帮他设计一种方案，可以在最短的时间内将整段道路的下陷深度都变为 0 。\n输入 输入文件包含两行，第一行包含一个整数 n，表示道路的长度。 第二行包含 n个整数，相邻两数间用一个空格隔开，第 i 个整数为 d_i。 n\u0026lt;=100000，d_i\u0026lt;=10000\n输出 输出文件仅包含一个整数，即最少需要多少天才能完成任务。\n输入样例 6 4 3 2 5 3 5 输出样例 9 解法: 依次扫描，如果后一个大于前一个，则将差值进行累加，最后的总和即为ans\n代码： #include\u0026lt;stdio.h\u0026gt; using namespace std; int main() { int n; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); long long ans = 0; int now = 0; while(n--) { int a; scanf(\u0026#34;%d\u0026#34;, \u0026amp;a); if(a \u0026gt; now) ans += a - now; now = a; } printf(\u0026#34;%lld\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2462-%E9%93%BA%E8%AE%BE%E9%81%93%E8%B7%AF/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e春春是一名道路工程师，负责铺设一条长度为 n 的道路。\u003c/p\u003e\n\u003cp\u003e铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n 块首尾相连的区域，一开始，第 i 块区域下陷的深度为 𝑑𝑖 。\u003c/p\u003e\n\u003cp\u003e春春每天可以选择一段连续区间[L,R] ，填充这段区间中的每块区域，让其下陷深度减少 1。在选择区间时，需要保证，区间内的每块区域在填充前下陷深度均不为 0 。\u003c/p\u003e\n\u003cp\u003e春春希望你能帮他设计一种方案，可以在最短的时间内将整段道路的下陷深度都变为 0 。\u003c/p\u003e","title":"51nod-2462-铺设道路"},{"content":"题目 有一个变进制系统从低位到高位的权值依次是 1，3，7，15，31，\u0026hellip; 。即第i（i\u0026gt;=0）位的权值是 2𝑖+1−1 。每一位数字是0，1，或者2。现在有一个十进制的数字n，想要把它转换成变进制系统下面的表示。由于有2的存在，这种转换可能会有多种可能，现在规定2只能作为最低非0位出现，这种情况下，表示就唯一了。\n比如44可能用15+15+7+7(2200)来表示，但是这样前面那个2就没有作为最低非0位出现，所以不符合要求，正确的转换是10120。\n输入 多组测试数据。 第一行有一个整数T（1\u0026lt;=T\u0026lt;=5），表示测试数据的数目。 接下来T行，每行一个整数n（0\u0026lt;=n\u0026lt;=1000000000）。\n输出 对于每一个n，输出它的变进制表示。\n输入样例 样例输入1\n4 1 2 3 4 输出样例 样例输出1\n1 2 10 11 解法： 暴力即可\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; #include\u0026lt;queue\u0026gt; using namespace std; typedef long long ll; ll POW(ll n, ll m) { ll ans = 1; for(int i = 0; i \u0026lt; m; i++) ans *= n; return ans; } int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--){ ll n,p; scanf(\u0026#34;%lld\u0026#34;, \u0026amp;n); if(n == 0) { printf(\u0026#34;0\\n\u0026#34;); continue; } queue\u0026lt;int\u0026gt; q; for(int i = 0; i \u0026lt; 40; i++){ while(!q.empty()) q.pop(); p = n - 2*POW(2,i) + 2; for(int j = 35; j \u0026gt;= 1; j--) { if(j == i){ q.push(2); if(p != 0){ p = -1; break; } continue; } if(p \u0026gt;= POW(2,j) - 1){ p -= POW(2,j) - 1; q.push(1); } else{ q.push(0); } } if(p == 0){ while(q.front() == 0){ q.pop(); } while(!q.empty()){ printf(\u0026#34;%d\u0026#34;,q.front()); q.pop(); } break; } } printf(\u0026#34;\\n\u0026#34;); } } ","permalink":"https://eonh1u.github.io/posts/51nod-1925-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/","summary":"\u003ch1 id=\"题目\"\u003e题目\u003c/h1\u003e\n\u003cp\u003e有一个变进制系统从低位到高位的权值依次是 1，3，7，15，31，\u0026hellip; 。即第i（i\u0026gt;=0）位的权值是 2𝑖+1−1 。每一位数字是0，1，或者2。现在有一个十进制的数字n，想要把它转换成变进制系统下面的表示。由于有2的存在，这种转换可能会有多种可能，现在规定2只能作为最低非0位出现，这种情况下，表示就唯一了。\u003c/p\u003e\n\u003cp\u003e比如44可能用15+15+7+7(2200)来表示，但是这样前面那个2就没有作为最低非0位出现，所以不符合要求，正确的转换是10120。\u003c/p\u003e","title":"51nod-1925-进制转换"},{"content":"题目： 给出一个字符串S，你需要从S中挑选一对字符进行一次交换（不可以不交换！！！！！！），并让得到的新字符字典序最小！\n例如：S = \u0026ldquo;abacc\u0026rdquo;，\n如果交换字符1(a)和4(c)，得到字符\u0026quot;cbaac\u0026quot;。\n如果交换字符2(a)和3(b)，得到字符\u0026quot;aabcc\u0026quot;。\n其中：\u0026ldquo;aabcc\u0026quot;的字典序小于\u0026quot;cbaac\u0026rdquo;。并且\u0026quot;aabcc\u0026quot;是所有交换方法中，字典序最小的。\n例如：S = \u0026ldquo;aaab\u0026rdquo;，\n则交换1和2，交换1和3，得到的字符都是 \u0026ldquo;aaab\u0026rdquo;，并且 \u0026ldquo;aaab\u0026quot;是所有交换方法中，字典序最小的。\n输出这个字典序最小的字符。\n输入 一个字符串S（S的只包括a到z的小写字符，2\u0026lt;=S的长度\u0026lt;=500000）。\n输出 字典序最小的新字符串。\n输入样例 abacc 输出样例 aabcc 解法： 原字符串与排序后字符串进行比较，如果相同的话并且有重复字符的话，结果就是原来字符，如果没有相同的字符，则将最后两个字符进行交换；如果不相同的话，则找到第一个不相同的字符，在原字符串找到最后一次出现的进行交换的字符进行交换（具体看代码）\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string.h\u0026gt; using namespace std; char s[500010]; char p[500010]; int main() { scanf(\u0026#34;%s\u0026#34;, s); strcpy(p,s); int len = strlen(s); sort(s, s + len); if(strcmp(s,p) == 0){ bool flag = false; for(int i = 1; i \u0026lt; len; i++) { if(s[i] == s[i - 1]) { printf(\u0026#34;%s\u0026#34;, s); flag = true; break; } } if(!flag){ swap(s[len - 2], s[len - 1]); printf(\u0026#34;%s\u0026#34;, s); } } else{ int i = 0; while(s[i] == p[i]) i++; char now = p[i]; p[i] = s[i]; int j = len - 1; while(p[j] != s[i]) j--; p[j] = now; printf(\u0026#34;%s\u0026#34;, p); } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1506-%E6%9C%80%E5%B0%8F%E5%AD%97%E5%85%B8%E5%BA%8F/","summary":"\u003ch1 id=\"题目\"\u003e题目：\u003c/h1\u003e\n\u003cp\u003e给出一个字符串S，你需要从S中挑选一对字符进行一次交换（不可以不交换！！！！！！），并让得到的新字符字典序最小！\u003c/p\u003e\n\u003cp\u003e例如：S = \u0026ldquo;abacc\u0026rdquo;，\u003c/p\u003e\n\u003cp\u003e如果交换字符1(a)和4(c)，得到字符\u0026quot;cbaac\u0026quot;。\u003c/p\u003e\n\u003cp\u003e如果交换字符2(a)和3(b)，得到字符\u0026quot;aabcc\u0026quot;。\u003c/p\u003e\n\u003cp\u003e其中：\u0026ldquo;aabcc\u0026quot;的字典序小于\u0026quot;cbaac\u0026rdquo;。并且\u0026quot;aabcc\u0026quot;是所有交换方法中，字典序最小的。\u003c/p\u003e\n\u003cp\u003e例如：S = \u0026ldquo;aaab\u0026rdquo;，\u003c/p\u003e\n\u003cp\u003e则交换1和2，交换1和3，得到的字符都是 \u0026ldquo;aaab\u0026rdquo;，并且 \u0026ldquo;aaab\u0026quot;是所有交换方法中，字典序最小的。\u003c/p\u003e\n\u003cp\u003e输出这个字典序最小的字符。\u003c/p\u003e","title":"51nod-1506-最小字典序"},{"content":"A: CME 题目： Let\u0026rsquo;s denote correct match equation (we will denote it as CME) an equation 𝑎+𝑏=𝑐 there all integers 𝑎, 𝑏 and 𝑐 are greater than zero.\nFor example, equations 2+2=4 (||+||=||||) and 1+2=3 (|+||=|||) are CME but equations 1+2=4 (|+||=||||), 2+2=3 (||+||=|||), and 0+1=1 (+|=|) are not.\nNow, you have 𝑛 matches. You want to assemble a CME using all your matches. Unfortunately, it is possible that you can\u0026rsquo;t assemble the CME using all matches. But you can buy some extra matches and then assemble CME!\nFor example, if 𝑛=2, you can buy two matches and assemble |+|=||, and if 𝑛=5 you can buy one match and assemble ||+|=|||. Calculate the minimum number of matches which you have to buy for assembling CME.\nNote, that you have to answer 𝑞 independent queries.\nInput The first line contains one integer 𝑞 (1≤𝑞≤100) — the number of queries.\nThe only line of each query contains one integer 𝑛 (2≤𝑛≤109) — the number of matches.\nOutput For each test case print one integer in single line — the minimum number of matches which you have to buy for assembling CME.\nExample input\n4 2 5 8 11 output\n2 1 0 1 解法： 满足火柴最小根数的式子是|+|=|| 因此当火柴根数小于4时，输出火柴根数与4的差值。当火柴根数大于4时，如果是偶数则可以组成满足条件的式子，是奇数时则需要补充一根。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;set\u0026gt; using namespace std; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); while(n--) { int a; scanf(\u0026#34;%d\u0026#34;, \u0026amp;a); if(a \u0026lt;= 4) printf(\u0026#34;%d\\n\u0026#34;, 4 -a); else if(a\u0026amp;1) printf(\u0026#34;1\\n\u0026#34;); else { printf(\u0026#34;0\\n\u0026#34;); } } return 0; } B：Strings Equalization 题目： You are given two strings of equal length 𝑠 and 𝑡 consisting of lowercase Latin letters. You may perform any number (possibly, zero) operations on these strings.\nDuring each operation you choose two adjacent characters in any string and assign the value of the first character to the value of the second or vice versa.\nFor example, if 𝑠 is \u0026ldquo;acbc\u0026rdquo; you can get the following strings in one operation:\n\u0026ldquo;aabc\u0026rdquo; (if you perform 𝑠2=𝑠1); \u0026ldquo;ccbc\u0026rdquo; (if you perform 𝑠1=𝑠2); \u0026ldquo;accc\u0026rdquo; (if you perform 𝑠3=𝑠2 or 𝑠3=𝑠4); \u0026ldquo;abbc\u0026rdquo; (if you perform 𝑠2=𝑠3); \u0026ldquo;acbb\u0026rdquo; (if you perform 𝑠4=𝑠3); Note that you can also apply this operation to the string 𝑡.\nPlease determine whether it is possible to transform 𝑠 into 𝑡, applying the operation above any number of times.\nNote that you have to answer 𝑞 independent queries.\nInput The first line contains one integer 𝑞 (1≤𝑞≤100) — the number of queries. Each query is represented by two consecutive lines.\nThe first line of each query contains the string 𝑠 (1≤|𝑠|≤100) consisting of lowercase Latin letters.\nThe second line of each query contains the string 𝑡 (1≤|𝑡|≤100, |𝑡|=|𝑠|) consisting of lowercase Latin letters.\nOutput For each query, print \u0026ldquo;YES\u0026rdquo; if it is possible to make 𝑠 equal to 𝑡, and \u0026ldquo;NO\u0026rdquo; otherwise.\nYou may print every letter in any case you want (so, for example, the strings \u0026ldquo;yEs\u0026rdquo;, \u0026ldquo;yes\u0026rdquo;, \u0026ldquo;Yes\u0026rdquo;, and \u0026ldquo;YES\u0026rdquo; will all be recognized as positive answer).\nExample input\n3 xabb aabx technocup technocup a z output\nYES YES NO 解法: 遍历两个字符串，如果存在有相同的字母，则满足。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;cstring\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;string.h\u0026gt; #include\u0026lt;set\u0026gt; using namespace std; int a[26]; int b[26]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); while(n--) { char s1[110],s2[110]; scanf(\u0026#34;%s\u0026#34;, s1); scanf(\u0026#34;%s\u0026#34;, s2); int l1 = strlen(s1); for(int i = 0; i \u0026lt; l1; i++){ a[s1[i] - \u0026#39;a\u0026#39;]++; b[s2[i] - \u0026#39;a\u0026#39;]++; } bool flag = false; for(int i = 0; i \u0026lt; 26; i++){ if(a[i]\u0026gt;0 \u0026amp;\u0026amp; b[i]\u0026gt;0) { flag = true; break; } } if(flag) printf(\u0026#34;YES\\n\u0026#34;); else { printf(\u0026#34;NO\\n\u0026#34;); } for(int i = 0; i \u0026lt; 26; i++){ a[i] = b[i] = 0; } } return 0; } C: Save the Nature 题目 You are an environmental activist at heart but the reality is harsh and you are just a cashier in a cinema. But you can still do something!\nYou have 𝑛 tickets to sell. The price of the 𝑖-th ticket is 𝑝𝑖. As a teller, you have a possibility to select the order in which the tickets will be sold (i.e. a permutation of the tickets). You know that the cinema participates in two ecological restoration programs applying them to the order you chose:\nThe 𝑥% of the price of each the 𝑎-th sold ticket (𝑎-th, 2𝑎-th, 3𝑎-th and so on) in the order you chose is aimed for research and spreading of renewable energy sources. The 𝑦% of the price of each the 𝑏-th sold ticket (𝑏-th, 2𝑏-th, 3𝑏-th and so on) in the order you chose is aimed for pollution abatement. If the ticket is in both programs then the (𝑥+𝑦)% are used for environmental activities. Also, it\u0026rsquo;s known that all prices are multiples of 100, so there is no need in any rounding.\nFor example, if you\u0026rsquo;d like to sell tickets with prices [400,100,300,200] and the cinema pays 10% of each 2-nd sold ticket and 20% of each 3-rd sold ticket, then arranging them in order [100,200,300,400] will lead to contribution equal to 100⋅0+200⋅0.1+300⋅0.2+400⋅0.1=120. But arranging them in order [100,300,400,200] will lead to 100⋅0+300⋅0.1+400⋅0.2+200⋅0.1=130.\nNature can\u0026rsquo;t wait, so you decided to change the order of tickets in such a way, so that the total contribution to programs will reach at least 𝑘 in minimum number of sold tickets. Or say that it\u0026rsquo;s impossible to do so. In other words, find the minimum number of tickets which are needed to be sold in order to earn at least 𝑘.\nInput The first line contains a single integer 𝑞 (1≤𝑞≤100) — the number of independent queries. Each query consists of 5 lines.\nThe first line of each query contains a single integer 𝑛 (1≤𝑛≤2⋅105) — the number of tickets.\nThe second line contains 𝑛 integers 𝑝1,𝑝2,…,𝑝𝑛 (100≤𝑝𝑖≤109, 𝑝𝑖mod100=0) — the corresponding prices of tickets.\nThe third line contains two integers 𝑥 and 𝑎 (1≤𝑥≤100, 𝑥+𝑦≤100, 1≤𝑎≤𝑛) — the parameters of the first program.\nThe fourth line contains two integers 𝑦 and 𝑏 (1≤𝑦≤100, 𝑥+𝑦≤100, 1≤𝑏≤𝑛) — the parameters of the second program.\nThe fifth line contains single integer 𝑘 (1≤𝑘≤1014) — the required total contribution.\nIt\u0026rsquo;s guaranteed that the total number of tickets per test doesn\u0026rsquo;t exceed 2⋅105.\nOutput Print 𝑞 integers — one per query.\nFor each query, print the minimum number of tickets you need to sell to make the total ecological contribution of at least 𝑘 if you can sell tickets in any order.\nIf the total contribution can not be achieved selling all the tickets, print −1.\nExample input\n4 1 100 50 1 49 1 100 8 100 200 100 200 100 200 100 100 10 2 15 3 107 3 1000000000 1000000000 1000000000 50 1 50 1 3000000000 5 200 100 100 100 100 69 5 31 2 90 output\n-1 6 3 4 解法： 二分+贪心 首先将数值按从大到小顺序进行排序，二分所需要的个数，在判断时，求出a与b的最小公倍数ab，在进行分配数值时按照以下顺序进行分配（x为二分时的长度)\n存在x/ab个最小公倍数ab的倍数，将前x/ab个数值放置在这些位置 判断a与b的大小，此处假设a较大，则再将n/a - n/ab个位置填满，数值数组依次填。 将n/b - n/ab的位置继续填满 判断经过上述分配所能得到的收益与k进行比较 返回二分结果\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;string.h\u0026gt; using namespace std; int num[200010]; int n; long long x,a,y,b; long long k; long long ab; long long sum[200010]; int gcd(int aa, int bb) { if(aa \u0026lt; bb) swap(aa,bb); if(bb==0) return aa; return gcd(bb,aa%bb); } bool c(int len) { //printf(\u0026#34;len:%d\\n\u0026#34;,len); long long SUM = 0; long long s1 = len/ab; long long s2 = len/a; long long s3 = len/b; long long mi = x,ma = y; int lmi = s2,lma = s3; if(x \u0026gt; y ){ mi = y; lmi = s3; ma = x; lma = s2; } //printf(\u0026#34;s1:%lld s2:%lld s3:%lld mi:%lld ma:%lld\\n\u0026#34;,s1,s2,s3,mi,ma); SUM += (x+y)*sum[s1]/100; // printf(\u0026#34;%d\\n\u0026#34;, SUM); SUM += ma*(sum[s1+lma-s1] - sum[s1])/100; // printf(\u0026#34;%d\\n\u0026#34;, SUM); SUM += mi*(sum[s1+s2-s1+s3-s1] - sum[s1+lma-s1])/100; // printf(\u0026#34;%d\\n\u0026#34;, SUM); return SUM \u0026gt;= k; } bool cmp(int xx, int yy) { return xx\u0026gt;yy; } void solve() { sort(num + 1, num + n + 1,cmp); memset(sum,0,sizeof(sum)); for(int i = 1; i \u0026lt;= n; i++){ sum[i] += sum[i - 1]+ num[i]; } int GCD = gcd(a,b); ab = a*b/GCD; if(!c(n)) { printf(\u0026#34;-1\\n\u0026#34;); return; } int l = 1, r = n, m = 0; for(int i = 0; i \u0026lt; 200; i++) { m = (l + r) / 2; if(c(m)) r = m; else l = m + 1; } if(c(l)) printf(\u0026#34;%d\\n\u0026#34;,l); else if(c(r)) printf(\u0026#34;%d\\n\u0026#34;,r); } int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--) { scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 1; i \u0026lt;= n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;num[i]); scanf(\u0026#34;%lld%lld\u0026#34;,\u0026amp;x, \u0026amp;a); scanf(\u0026#34;%lld%lld\u0026#34;,\u0026amp;y, \u0026amp;b); scanf(\u0026#34;%lld\u0026#34;,\u0026amp;k); solve(); } } D:Sequence Sorting 题目： You are given a sequence 𝑎1,𝑎2,…,𝑎𝑛, consisting of integers.\nYou can apply the following operation to this sequence: choose some integer 𝑥 and move all elements equal to 𝑥 either to the beginning, or to the end of 𝑎. Note that you have to move all these elements in one direction in one operation.\nFor example, if 𝑎=[2,1,3,1,1,3,2], you can get the following sequences in one operation (for convenience, denote elements equal to 𝑥 as 𝑥-elements):\n[1,1,1,2,3,3,2] if you move all 1-elements to the beginning; [2,3,3,2,1,1,1] if you move all 1-elements to the end; [2,2,1,3,1,1,3] if you move all 2-elements to the beginning; [1,3,1,1,3,2,2] if you move all 2-elements to the end; [3,3,2,1,1,1,2] if you move all 3-elements to the beginning; [2,1,1,1,2,3,3] if you move all 3-elements to the end; You have to determine the minimum number of such operations so that the sequence 𝑎 becomes sorted in non-descending order. Non-descending order means that for all 𝑖 from 2 to 𝑛, the condition 𝑎𝑖−1≤𝑎𝑖 is satisfied.\nNote that you have to answer 𝑞 independent queries.\nInput The first line contains one integer 𝑞 (1≤𝑞≤3⋅10^5) — the number of the queries. Each query is represented by two consecutive lines.\nThe first line of each query contains one integer 𝑛 (1≤𝑛≤3⋅10^5) — the number of elements.\nThe second line of each query contains 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤𝑛) — the elements.\nIt is guaranteed that the sum of all 𝑛 does not exceed 3⋅10^5.\nOutput For each query print one integer — the minimum number of operation for sorting sequence 𝑎 in non-descending order.\nExample input\n3 7 3 1 6 6 3 1 1 8 1 1 4 4 4 7 8 8 7 4 2 5 2 6 2 7 output\n2 0 1 解法： 首先将数组的值连续化，同时将相同的数字进行删减，只保留最先出现与最晚出现的，想要使得移动的次数最少，我们则需要找到最长的一个连续递增序列，递增的连续序列。此处的递增必须数字挨着递增，差值为1.\n代码: #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string.h\u0026gt; using namespace std; int a[300010]; int v[300010]; int MAX[300010]; int MIN[300010]; const int inf = 99999999; int dp[300010]; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--) { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); v[i] = a[i]; } sort(v, v + n); int len = unique(v, v + n) - v; // printf(\u0026#34;%d\\n\u0026#34;, len); for(int i = 0; i \u0026lt; n; i++) a[i] = lower_bound(v, v + len,a[i]) - v + 1; //for(int i = 0; i \u0026lt; n; i++) // printf(\u0026#34;%d \u0026#34;, a[i]); // printf(\u0026#34;\\n\u0026#34;); for(int i = 0; i \u0026lt;= n; i++){ MAX[i] = -inf;MIN[i] = inf; } for(int i = 0; i \u0026lt; n; i++){ MAX[a[i]] = max(MAX[a[i]],i + 1); MIN[a[i]] = min(MIN[a[i]],i + 1); // printf(\u0026#34;%d %d %d\\n\u0026#34;, i,MAX[i],MIN[i]); } int ans = 0; for(int i = 1; i \u0026lt;= len; i++) { // printf(\u0026#34;%d %d %d\\n\u0026#34;, i,MAX[i],MIN[i]); if(MIN[i] \u0026gt; MAX[i - 1]) dp[i] = dp[i - 1] + 1; else { dp[i] = 1; } // printf(\u0026#34;dp[%d] = %d\\n\u0026#34;, i,dp[i]); ans = max(ans, dp[i]); } printf(\u0026#34;%d\\n\u0026#34;, len - ans); } return 0; } ","permalink":"https://eonh1u.github.io/posts/cf-591-div2/","summary":"\u003ch1 id=\"a-cme\"\u003eA: CME\u003c/h1\u003e\n\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eLet\u0026rsquo;s denote correct match equation (we will denote it as CME) an equation 𝑎+𝑏=𝑐 there all integers 𝑎, 𝑏 and 𝑐 are greater than zero.\u003c/p\u003e\n\u003cp\u003eFor example, equations 2+2=4 (||+||=||||) and 1+2=3 (|+||=|||) are CME but equations 1+2=4 (|+||=||||), 2+2=3 (||+||=|||), and 0+1=1 (+|=|) are not.\u003c/p\u003e\n\u003cp\u003eNow, you have 𝑛 matches. You want to assemble a CME using all your matches. Unfortunately, it is possible that you can\u0026rsquo;t assemble the CME using all matches. But you can buy some extra matches and then assemble CME!\u003c/p\u003e","title":"cf-591-div2"},{"content":"A： Given an array of size n, ﬁnd the majority element. The majority element is the element that appears more than b n c times.You may assume that the array is non-empty and the majority 2 element always exist in the array.\nINPUT:\nLine 1: the length of array.\nLine 2: the all elements in array and split by spaces OUTPUT:\nLine 1: A single integer that is the majority element.\n解法：map存储出现数量，同时更新ans即可\n#include\u0026lt;stdio.h\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; map\u0026lt;int, int\u0026gt; m; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int MAX = 0, ans =0; while(n--) { int a; scanf(\u0026#34;%d\u0026#34;, \u0026amp;a); m[a]++; if(m[a] \u0026gt; MAX){ MAX = m[a]; ans = a; } } printf(\u0026#34;%d\\n\u0026#34;, ans); } B: Given a 2d m * n grid map of ’1’s (land) and ’0’s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.\nINPUT:\nLine 1: m and n.\nLine 2: ’1’ or ’0’ in grid and split by spaces OUTPUT:\nLine 1: number of islands. 解法:dfs水题\n#include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int s[1010][1010]; int n,m; int yd[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; void dfs(int x, int y) { for(int i = 0; i \u0026lt; 4; i++){ int xx = x + yd[i][0]; int yy = y + yd[i][1]; if(xx \u0026gt;= 0 \u0026amp;\u0026amp; xx \u0026lt; n \u0026amp;\u0026amp; yy \u0026gt;= 0 \u0026amp;\u0026amp; yy \u0026lt; m){ if(s[xx][yy] == 1){ s[xx][yy] = 0; dfs(xx,yy); } } } } int main() { int ans = 0; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;n, \u0026amp;m); for(int i = 0; i \u0026lt; n; i++) for(int j = 0; j \u0026lt; m; j++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;s[i][j]); for(int i = 0; i \u0026lt; n; i++) for(int j = 0; j \u0026lt; m; j++){ if(s[i][j] == 1){ ans++; s[i][j] = 0; dfs(i, j); } } printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/ucas-2%E5%B0%8F%E9%A2%98/","summary":"\u003ch1 id=\"a\"\u003eA：\u003c/h1\u003e\n\u003cp\u003eGiven an array of size n, ﬁnd the majority element. The majority element is the element that appears more than b n c times.You may assume that the array is non-empty and the majority 2 element always exist in the array.\u003c/p\u003e\n\u003cp\u003eINPUT:\u003c/p\u003e\n\u003cp\u003eLine 1: the length of array.\u003c/p\u003e\n\u003cp\u003eLine 2: the all elements in array and split by spaces OUTPUT:\u003c/p\u003e\n\u003cp\u003eLine 1: A single integer that is the majority element.\u003c/p\u003e","title":"ucas 2小题"},{"content":"题目: 考虑股票市场，一共有n天。 对于第i天，B君知道股票的价格是每单位a[i]元 在每一天，B君可以选择买入一个单位的股票，卖出一个单位的股票，或者什么都不做。 刚开始B君有无穷多的钱，但是没有任何股票。 问n天之后B君最多可以赚多少钱。 (1 \u0026lt;= n \u0026lt;= 200000) (1 \u0026lt;= a[i] \u0026lt;= 10000)\n输入 第一行一个整数n表示天数。 接下来一行n个整数，表示每天的价钱。\n输出 一行一个整数表示最多可以赚的钱数。 输入样例\n9 10 5 4 7 9 12 6 2 10 输出样例\n20 题解： 利用优先队列建立最小堆，遍历时，每次首先push当前a[i]两次，取堆中的最小值，若堆中最小值为a[i]，相当于未进行操作。 下面解释一下为何要push两次 1.堆里面存储的值，相当于已经买的股票，因此第一次push可以认为购买了当天的股票。 2.从堆中取出最小值之后，ans加上当前a[i]与堆中最小元素的差值，此时第二次push的a[i]可以认为是堆中最小元素的一个跳板，以备以后出现利润更高的天数。 例子：1 3 9 day1: \u0026lt;1,1\u0026gt; \u0026lt;1\u0026gt; ans = 0 day2: \u0026lt;1,3,3\u0026gt; \u0026lt;3,3\u0026gt; ans = 2 day3: \u0026lt;3,3,9,9\u0026gt; \u0026lt;3,9,9\u0026gt; ans = 2+9-3 = 8 根据上述例子，我们可以看到在第三天时，取到了堆中最小的元素3，此时的元素3是由元素1变化而来的，最终的ans为8，即1-\u0026gt;3 3-\u0026gt;9 ,可以认为1-\u0026gt;9 即第一天买入，第二天不进行操作，第三天卖出。而当第三天结束时，我们可以看到仍有一个元素3存在，这就是假设购入了第二天的股票，以备后面的进行比较。 第二个例子：1 3 9 10 day1：\u0026lt;1,1\u0026gt; \u0026lt;1\u0026gt; ans = 0 day2:\u0026lt;1,3,3\u0026gt; \u0026lt;3,3\u0026gt; ans = 2 day3:\u0026lt;3,3,9,9\u0026gt; \u0026lt;3,9,9\u0026gt; ans = 8 day4：\u0026lt;3,9,9,10,10\u0026gt; \u0026lt;9,9,10,10\u0026gt; ans = 15 可以看出在day2结束时\u0026lt;3,3\u0026gt; 一个为元素1转化而来，一个为元素3，分别在day3，day4被选取。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; const int maxn = 200010; int a[maxn]; priority_queue\u0026lt;int\u0026gt; s; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); long long ans = 0; for(int i = 0; i \u0026lt; n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); s.push(-a[i]); s.push(-a[i]); ans += a[i] + s.top(); s.pop(); } printf(\u0026#34;%lld\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2206-%E4%BD%8E%E4%B9%B0%E9%AB%98%E5%8D%96/","summary":"\u003ch1 id=\"题目\"\u003e题目:\u003c/h1\u003e\n\u003cp\u003e考虑股票市场，一共有n天。\n对于第i天，B君知道股票的价格是每单位a[i]元\n在每一天，B君可以选择买入一个单位的股票，卖出一个单位的股票，或者什么都不做。\n刚开始B君有无穷多的钱，但是没有任何股票。\n问n天之后B君最多可以赚多少钱。\n(1 \u0026lt;= n \u0026lt;= 200000)\n(1 \u0026lt;= a[i] \u0026lt;= 10000)\u003c/p\u003e","title":"51nod-2206-低买高卖"},{"content":"题目 在一个叫奥斯汀的城市，有n个小镇（从1到n编号），这些小镇通过m条双向火车铁轨相连。当然某些小镇之间也有公路相连。为了保证每两个小镇之间的人可以方便的相互访问，市长就在那些没有铁轨直接相连的小镇之间建造了公路。在两个直接通过公路或者铁路相连的小镇之间移动，要花费一个小时的时间。\n现在有一辆火车和一辆汽车同时从小镇1出发。他们都要前往小镇n，但是他们中途不能同时停在同一个小镇（但是可以同时停在小镇n）。火车只能走铁路，汽车只能走公路。\n现在请来为火车和汽车分别设计一条线路；所有的公路或者铁路可以被多次使用。使得火车和汽车尽可能快的到达小镇n。即要求他们中最后到达小镇n的时间要最短。输出这个最短时间。(最后火车和汽车可以同时到达小镇n，也可以先后到达。)\n样例解释： 在样例中，火车可以按照 1⟶3⟶4 行驶，汽车 1⟶2⟶4 按照行驶，经过2小时后他们同时到过小镇4。\n输入 单组测试数据。 第一行有两个整数n 和 m (2≤n≤400, 0≤m≤n*(n-1)/2) ，表示小镇的数目和铁轨的数目。 接下来m行，每行有两个整数u 和 v，表示u和v之间有一条铁路。(1≤u,v≤n, u≠v)。 输入中保证两个小镇之间最多有一条铁路直接相连。 输出 输出一个整数，表示答案，如果没有合法的路线规划，输出-1。 输入样例\n4 2 1 3 3 4 输出样例\n2 解法: 两次最短路取最大值即可。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;vector\u0026gt; #include\u0026lt;set\u0026gt; using namespace std; struct Node { int to; long long len; bool operator\u0026lt;(const Node \u0026amp;a) const { return len \u0026gt; a.len; } }; bool isUsed[510]; long long ans[510]; vector\u0026lt;Node\u0026gt; NodeQueue[510]; set\u0026lt;int\u0026gt; sto[510]; void addEdge(int s, int e, int len) { NodeQueue[s].push_back((Node){e,len}); NodeQueue[e].push_back((Node){s,len}); } int n,m; priority_queue\u0026lt;Node\u0026gt; PriNodeQueue; long long len(int s, int t) { for(int i = 0; i \u0026lt; 505; i++) ans[i] = 999999999999; ans[s] = 0; PriNodeQueue.push((Node){s,0}); while(!PriNodeQueue.empty()){ Node now = PriNodeQueue.top(); PriNodeQueue.pop(); int u = now.to; if(!isUsed[u]){ isUsed[u] = true; for(int i = 0; i \u0026lt; NodeQueue[u].size(); i++){ if(!isUsed[NodeQueue[u][i].to]){ int v = NodeQueue[u][i].to; int len = NodeQueue[u][i].len; if(ans[v] \u0026gt; ans[u] + len) { ans[v] = ans[u] + len; PriNodeQueue.push((Node){v,ans[v]}); } } } } } return ans[t]; } int main() { scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;n, \u0026amp;m); while(m--) { int s, e, len; scanf(\u0026#34;%d%d\u0026#34;,\u0026amp;s, \u0026amp;e); sto[s].insert(e); sto[e].insert(s); addEdge(s, e, 1); } long long ans1 = len(1,n); fill(isUsed, isUsed + 510, 0); for(int i = 0; i \u0026lt; 510; i++) NodeQueue[i].clear(); for(int i = 1; i \u0026lt;= n; i++) for(int j = 1; j \u0026lt;= n; j++) if(i != j \u0026amp;\u0026amp; sto[i].find(j) == sto[i].end()) addEdge(i,j,1); long long ans2 = len(1,n); long long ans = max(ans1, ans2); if(ans != 999999999999) printf(\u0026#34;%lld\\n\u0026#34;, ans); else { printf(\u0026#34;-1\u0026#34;); } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1649-%E9%BD%90%E5%A4%B4%E5%B9%B6%E8%BF%9B/","summary":"\u003ch1 id=\"题目\"\u003e题目\u003c/h1\u003e\n\u003cp\u003e在一个叫奥斯汀的城市，有n个小镇（从1到n编号），这些小镇通过m条双向火车铁轨相连。当然某些小镇之间也有公路相连。为了保证每两个小镇之间的人可以方便的相互访问，市长就在那些没有铁轨直接相连的小镇之间建造了公路。在两个直接通过公路或者铁路相连的小镇之间移动，要花费一个小时的时间。\u003c/p\u003e\n\u003cp\u003e现在有一辆火车和一辆汽车同时从小镇1出发。他们都要前往小镇n，但是他们中途不能同时停在同一个小镇（但是可以同时停在小镇n）。火车只能走铁路，汽车只能走公路。\u003c/p\u003e\n\u003cp\u003e现在请来为火车和汽车分别设计一条线路；所有的公路或者铁路可以被多次使用。使得火车和汽车尽可能快的到达小镇n。即要求他们中最后到达小镇n的时间要最短。输出这个最短时间。(最后火车和汽车可以同时到达小镇n，也可以先后到达。)\u003c/p\u003e","title":"51nod-1649-齐头并进"},{"content":"A题 Prefixes： 题目： Nikolay got a string 𝑠 of even length 𝑛, which consists only of lowercase Latin letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;. Its positions are numbered from 1 to 𝑛.\nHe wants to modify his string so that every its prefix of even length has an equal amount of letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;. To achieve that, Nikolay can perform the following operation arbitrary number of times (possibly, zero): choose some position in his string and replace the letter on this position with the other letter (i.e. replace \u0026lsquo;a\u0026rsquo; with \u0026lsquo;b\u0026rsquo; or replace \u0026lsquo;b\u0026rsquo; with \u0026lsquo;a\u0026rsquo;). Nikolay can use no letters except \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;.\nThe prefix of string 𝑠 of length 𝑙 (1≤𝑙≤𝑛) is a string 𝑠[1..𝑙].\nFor example, for the string 𝑠=\u0026ldquo;abba\u0026rdquo; there are two prefixes of the even length. The first is 𝑠[1…2]=\u0026ldquo;ab\u0026rdquo; and the second 𝑠[1…4]=\u0026ldquo;abba\u0026rdquo;. Both of them have the same number of \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;.\nYour task is to calculate the minimum number of operations Nikolay has to perform with the string 𝑠 to modify it so that every its prefix of even length has an equal amount of letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;.\nInput The first line of the input contains one even integer 𝑛 (2≤𝑛≤2⋅105) — the length of string 𝑠.\nThe second line of the input contains the string 𝑠 of length 𝑛, which consists only of lowercase Latin letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;.\nOutput In the first line print the minimum number of operations Nikolay has to perform with the string 𝑠 to modify it so that every its prefix of even length has an equal amount of letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;.\nIn the second line print the string Nikolay obtains after applying all the operations. If there are multiple answers, you can print any of them.\nExamples input\n4 bbbb output\n2 abba input\n6 ababab output\n0 ababab input\n2 aa output\n1 ba Note In the first example Nikolay has to perform two operations. For example, he can replace the first \u0026lsquo;b\u0026rsquo; with \u0026lsquo;a\u0026rsquo; and the last \u0026lsquo;b\u0026rsquo; with \u0026lsquo;a\u0026rsquo;.\nIn the second example Nikolay doesn\u0026rsquo;t need to do anything because each prefix of an even length of the initial string already contains an equal amount of letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;.\n解法： 每两个字符判断是否相同，如果相同则需要更改一个字母。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; #include\u0026lt;string\u0026gt; using namespace std; int main() { string s; int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); cin \u0026gt;\u0026gt; s; int l = s.length(); //printf(\u0026#34;%d\\n\u0026#34;,l); int l1 = 0, l2 = 0; for(int i = 0; i \u0026lt; l/2; i++) { if(s[2*i] == s[2*i+1]) { l1++; if(s[2*i] == \u0026#39;a\u0026#39;) s[2*i] = \u0026#39;b\u0026#39;; else { s[2*i]=\u0026#39;a\u0026#39;; } } } printf(\u0026#34;%d\\n\u0026#34;,l1); cout\u0026lt;\u0026lt;s; return 0; } B题：Shooting 题目： Recently Vasya decided to improve his pistol shooting skills. Today his coach offered him the following exercise. He placed 𝑛 cans in a row on a table. Cans are numbered from left to right from 1 to 𝑛. Vasya has to knock down each can exactly once to finish the exercise. He is allowed to choose the order in which he will knock the cans down.\nVasya knows that the durability of the 𝑖-th can is 𝑎𝑖. It means that if Vasya has already knocked 𝑥 cans down and is now about to start shooting the 𝑖-th one, he will need (𝑎𝑖⋅𝑥+1) shots to knock it down. You can assume that if Vasya starts shooting the 𝑖-th can, he will be shooting it until he knocks it down.\nYour task is to choose such an order of shooting so that the number of shots required to knock each of the 𝑛 given cans down exactly once is minimum possible.\nInput The first line of the input contains one integer 𝑛 (2≤𝑛≤1000) — the number of cans.\nThe second line of the input contains the sequence 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤1000), where 𝑎𝑖 is the durability of the 𝑖-th can.\nOutput In the first line print the minimum number of shots required to knock each of the 𝑛 given cans down exactly once.\nIn the second line print the sequence consisting of 𝑛 distinct integers from 1 to 𝑛 — the order of indices of cans that minimizes the number of shots required. If there are several answers, you can print any of them.\nExamples 3 20 10 20 43 1 3 2 4 10 10 10 10 64 2 1 4 3 6 5 4 5 4 4 5 69 6 1 3 5 2 4 2 1 4 3 2 1 Note In the first example Vasya can start shooting from the first can. He knocks it down with the first shot because he haven\u0026rsquo;t knocked any other cans down before. After that he has to shoot the third can. To knock it down he shoots 20⋅1+1=21 times. After that only second can remains. To knock it down Vasya shoots 10⋅2+1=21 times. So the total number of shots is 1+21+21=43.\nIn the second example the order of shooting does not matter because all cans have the same durability.\n解法： 从大到小排序即可\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; struct point{ int x,status; }; bool cmp(point a, point b){ return a.x \u0026gt; b.x; } point p[10010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;p[i].x); p[i].status = i + 1; } sort(p, p + n, cmp); long long ans = 0; for(int i = 0; i \u0026lt; n; i++) ans += i * p[i].x + 1; printf(\u0026#34;%lld\\n\u0026#34;, ans); for(int i = 0; i \u0026lt; n; i++) printf(\u0026#34;%d \u0026#34;, p[i].status); return 0; } C题 White Sheet 题目： There is a white sheet of paper lying on a rectangle table. The sheet is a rectangle with its sides parallel to the sides of the table. If you will take a look from above and assume that the bottom left corner of the table has coordinates (0,0), and coordinate axes are left and bottom sides of the table, then the bottom left corner of the white sheet has coordinates (𝑥1,𝑦1), and the top right — (𝑥2,𝑦2).\nAfter that two black sheets of paper are placed on the table. Sides of both black sheets are also parallel to the sides of the table. Coordinates of the bottom left corner of the first black sheet are (𝑥3,𝑦3), and the top right — (𝑥4,𝑦4). Coordinates of the bottom left corner of the second black sheet are (𝑥5,𝑦5), and the top right — (𝑥6,𝑦6). Determine if some part of the white sheet can be seen from the above after the two black sheets are placed. The part of the white sheet can be seen if there is at least one point lying not strictly inside the white sheet and strictly outside of both black sheets.\nInput The first line of the input contains four integers 𝑥1,𝑦1,𝑥2,𝑦2 (0≤𝑥1\u0026lt;𝑥2≤106,0≤𝑦1\u0026lt;𝑦2≤106) — coordinates of the bottom left and the top right corners of the white sheet.\nThe second line of the input contains four integers 𝑥3,𝑦3,𝑥4,𝑦4 (0≤𝑥3\u0026lt;𝑥4≤106,0≤𝑦3\u0026lt;𝑦4≤106) — coordinates of the bottom left and the top right corners of the first black sheet.\nThe third line of the input contains four integers 𝑥5,𝑦5,𝑥6,𝑦6 (0≤𝑥5\u0026lt;𝑥6≤106,0≤𝑦5\u0026lt;𝑦6≤106) — coordinates of the bottom left and the top right corners of the second black sheet.\nThe sides of each sheet of paper are parallel (perpendicular) to the coordinate axes.\nOutput If some part of the white sheet can be seen from the above after the two black sheets are placed, print \u0026ldquo;YES\u0026rdquo; (without quotes). Otherwise print \u0026ldquo;NO\u0026rdquo;.\nExamples input\n2 2 4 4 1 1 3 5 3 1 5 5 output\nNO input\n3 3 7 5 0 0 4 6 0 0 7 4 output\nYES input\n5 2 10 5 3 1 7 6 8 1 11 7 output\nYES input\n0 0 1000000 1000000 0 0 499999 1000000 500000 0 1000000 1000000 output\nYES Note In the first example the white sheet is fully covered by black sheets.\nIn the second example the part of the white sheet can be seen after two black sheets are placed. For example, the point (6.5,4.5) lies not strictly inside the white sheet and lies strictly outside of both black sheets.\n解法： 此文用到的解法，求出两个黑块与白块分别的共同面积，再求出两个黑块在白块中共同的面积，这里要注意，必须是在白块中的共同面积，而不是两个黑块所有的共同面积，白块外的共同面积是无效的。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; long long f(long long x1, long long x2, long long y1, long long y2) { if(x1 \u0026lt; y1) { if(y1 \u0026gt;= x2) return 0; else{ if(y2 \u0026gt;= x2) return x2 - y1; else return y2 - y1; } } else { if(x1 \u0026gt;= y2) return 0; else{ if(x2 \u0026gt;= y2) return y2 - x1; else { return x2 - x1; } } } } long long s(long long x1, long long x2,long long x3,long long x4,long long y1,long long y2,long long y3,long long y4) { long long X = f(x1,x2,x3,x4); long long Y = f(y1,y2,y3,y4); long long ans = X*Y; return ans; } int main() { long long x[6],y[6]; for(int i = 0; i \u0026lt; 6; i++) scanf(\u0026#34;%lld%lld\u0026#34;, \u0026amp;x[i], \u0026amp;y[i]); long long now = (x[1] - x[0]) * (y[1] - y[0]); long long s1 = s(x[0],x[1],x[2],x[3],y[0],y[1],y[2],y[3]); long long s3 = s(x[0],x[1],x[4],x[5],y[0],y[1],y[4],y[5]); // printf(\u0026#34;%lld %lld %lld %lld\\n\u0026#34;, now ,s1,s2,s3); long long ans = now - s1 - s3; if(s1 \u0026gt; 0 \u0026amp;\u0026amp; s3 \u0026gt; 0) { long long Ax[4], Ay[4]; //s1 if(x[0] \u0026lt; x[2]) { Ax[0] = x[2]; if(x[1] \u0026lt; x[3]) Ax[1] = x[1]; else { Ax[1] = x[3]; } } else { Ax[0] = x[0]; if(x[3] \u0026lt; x[1]) Ax[1] = x[3]; else { Ax[1] = x[1]; } } if(y[0] \u0026lt; y[2]) { Ay[0] = y[2]; if(y[1] \u0026lt; y[3]) Ay[1] = y[1]; else { Ay[1] = y[3]; } } else { Ay[0] = y[0]; if(y[3] \u0026lt; y[1]) Ay[1] = y[3]; else { Ay[1] = y[1]; } } //s2 if(x[0] \u0026lt; x[4]) { Ax[2] = x[4]; if(x[1] \u0026lt; x[5]) Ax[3] = x[1]; else { Ax[3] = x[5]; } } else { Ax[2] = x[0]; if(x[5] \u0026lt; x[1]) Ax[3] = x[5]; else { Ax[3] = x[1]; } } if(y[0] \u0026lt; y[4]) { Ay[2] = y[4]; if(y[1] \u0026lt; y[5]) Ay[3] = y[1]; else { Ay[3] = y[5]; } } else { Ay[2] = y[0]; if(y[5] \u0026lt; y[1]) Ay[3] = y[5]; else { Ay[3] = y[1]; } } long long p = s(Ax[0],Ax[1],Ax[2],Ax[3],Ay[0],Ay[1],Ay[2],Ay[3]); //printf(\u0026#34;%lld %lld %lld %lld %lld %lld %lld %lld\\n\u0026#34;,Ax[0],Ax[1],Ax[2],Ax[3],Ay[0],Ay[1],Ay[2],Ay[3]); // printf(\u0026#34;%lld\\n\u0026#34;, p); ans += p; } if(ans \u0026gt; 0) printf(\u0026#34;YES\u0026#34;); else { printf(\u0026#34;NO\u0026#34;); } return 0; } D题 Swords 题目: There were 𝑛 types of swords in the theater basement which had been used during the plays. Moreover there were exactly 𝑥 swords of each type. 𝑦 people have broken into the theater basement and each of them has taken exactly 𝑧 swords of some single type. Note that different people might have taken different types of swords. Note that the values 𝑥,𝑦 and 𝑧 are unknown for you.\nThe next morning the director of the theater discovers the loss. He counts all swords — exactly 𝑎𝑖 swords of the 𝑖-th type are left untouched.\nThe director has no clue about the initial number of swords of each type in the basement, the number of people who have broken into the basement and how many swords each of them have taken.\nFor example, if 𝑛=3, 𝑎=[3,12,6] then one of the possible situations is 𝑥=12, 𝑦=5 and 𝑧=3. Then the first three people took swords of the first type and the other two people took swords of the third type. Note that you don\u0026rsquo;t know values 𝑥,𝑦 and 𝑧 beforehand but know values of 𝑛 and 𝑎.\nThus he seeks for your help. Determine the minimum number of people 𝑦, which could have broken into the theater basement, and the number of swords 𝑧 each of them has taken.\nInput The first line of the input contains one integer 𝑛 (2≤𝑛≤2⋅105) — the number of types of swords.\nThe second line of the input contains the sequence 𝑎1,𝑎2,…,𝑎𝑛 (0≤𝑎𝑖≤109), where 𝑎𝑖 equals to the number of swords of the 𝑖-th type, which have remained in the basement after the theft. It is guaranteed that there exists at least one such pair of indices (𝑗,𝑘) that 𝑎𝑗≠𝑎𝑘.\nOutput Print two integers 𝑦 and 𝑧 — the minimum number of people which could have broken into the basement and the number of swords each of them has taken.\nExamples input\n3 3 12 6 output\n5 3 input\n2 2 9 output\n1 7 input\n7 2 1000000000 4 6 8 4 2 outputCopy 2999999987 2 inputCopy 6 13 52 0 13 26 52 output\n12 13 Note In the first example the minimum value of 𝑦 equals to 5, i.e. the minimum number of people who could have broken into the basement, is 5. Each of them has taken 3 swords: three of them have taken 3 swords of the first type, and two others have taken 3 swords of the third type.\nIn the second example the minimum value of 𝑦 is 1, i.e. the minimum number of people who could have broken into the basement, equals to 1. He has taken 7 swords of the first type\n解法： 循环遍历数组，得到max，数组中不为max的数与max的差值，求出最大公约数，最大公约数即为每个人取走的数目。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; long long f(long long x1, long long x2, long long y1, long long y2) { if(x1 \u0026lt; y1) { if(y1 \u0026gt;= x2) return 0; else{ if(y2 \u0026gt;= x2) return x2 - y1; else return y2 - y1; } } else { if(x1 \u0026gt;= y2) return 0; else{ if(x2 \u0026gt;= y2) return y2 - x1; else { return x2 - x1; } } } } long long s(long long x1, long long x2,long long x3,long long x4,long long y1,long long y2,long long y3,long long y4) { long long X = f(x1,x2,x3,x4); long long Y = f(y1,y2,y3,y4); long long ans = X*Y; return ans; } int main() { long long x[6],y[6]; for(int i = 0; i \u0026lt; 6; i++) scanf(\u0026#34;%lld%lld\u0026#34;, \u0026amp;x[i], \u0026amp;y[i]); long long now = (x[1] - x[0]) * (y[1] - y[0]); long long s1 = s(x[0],x[1],x[2],x[3],y[0],y[1],y[2],y[3]); long long s3 = s(x[0],x[1],x[4],x[5],y[0],y[1],y[4],y[5]); // printf(\u0026#34;%lld %lld %lld %lld\\n\u0026#34;, now ,s1,s2,s3); long long ans = now - s1 - s3; if(s1 \u0026gt; 0 \u0026amp;\u0026amp; s3 \u0026gt; 0) { long long Ax[4], Ay[4]; //s1 if(x[0] \u0026lt; x[2]) { Ax[0] = x[2]; if(x[1] \u0026lt; x[3]) Ax[1] = x[1]; else { Ax[1] = x[3]; } } else { Ax[0] = x[0]; if(x[3] \u0026lt; x[1]) Ax[1] = x[3]; else { Ax[1] = x[1]; } } if(y[0] \u0026lt; y[2]) { Ay[0] = y[2]; if(y[1] \u0026lt; y[3]) Ay[1] = y[1]; else { Ay[1] = y[3]; } } else { Ay[0] = y[0]; if(y[3] \u0026lt; y[1]) Ay[1] = y[3]; else { Ay[1] = y[1]; } } //s2 if(x[0] \u0026lt; x[4]) { Ax[2] = x[4]; if(x[1] \u0026lt; x[5]) Ax[3] = x[1]; else { Ax[3] = x[5]; } } else { Ax[2] = x[0]; if(x[5] \u0026lt; x[1]) Ax[3] = x[5]; else { Ax[3] = x[1]; } } if(y[0] \u0026lt; y[4]) { Ay[2] = y[4]; if(y[1] \u0026lt; y[5]) Ay[3] = y[1]; else { Ay[3] = y[5]; } } else { Ay[2] = y[0]; if(y[5] \u0026lt; y[1]) Ay[3] = y[5]; else { Ay[3] = y[1]; } } long long p = s(Ax[0],Ax[1],Ax[2],Ax[3],Ay[0],Ay[1],Ay[2],Ay[3]); //printf(\u0026#34;%lld %lld %lld %lld %lld %lld %lld %lld\\n\u0026#34;,Ax[0],Ax[1],Ax[2],Ax[3],Ay[0],Ay[1],Ay[2],Ay[3]); // printf(\u0026#34;%lld\\n\u0026#34;, p); ans += p; } if(ans \u0026gt; 0) printf(\u0026#34;YES\u0026#34;); else { printf(\u0026#34;NO\u0026#34;); } return 0; } ","permalink":"https://eonh1u.github.io/posts/cf-587-div3/","summary":"\u003ch1 id=\"a题-prefixes\"\u003eA题 Prefixes：\u003c/h1\u003e\n\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eNikolay got a string 𝑠 of even length 𝑛, which consists only of lowercase Latin letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;. Its positions are numbered from 1 to 𝑛.\u003c/p\u003e\n\u003cp\u003eHe wants to modify his string so that every its prefix of even length has an equal amount of letters \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;. To achieve that, Nikolay can perform the following operation arbitrary number of times (possibly, zero): choose some position in his string and replace the letter on this position with the other letter (i.e. replace \u0026lsquo;a\u0026rsquo; with \u0026lsquo;b\u0026rsquo; or replace \u0026lsquo;b\u0026rsquo; with \u0026lsquo;a\u0026rsquo;). Nikolay can use no letters except \u0026lsquo;a\u0026rsquo; and \u0026lsquo;b\u0026rsquo;.\u003c/p\u003e","title":"cf-587-div3"},{"content":"昨天参加了cf—edu-73 div2。嗯 很菜 以后有时间多参加一下cf，提一下rating。\nA题 2048 Games： 题目： You are playing a variation of game 2048. Initially you have a multiset 𝑠 of 𝑛 integers. Every integer in this multiset is a power of two.\nYou may perform any number (possibly, zero) operations with this multiset.\nDuring each operation you choose two equal integers from 𝑠, remove them from 𝑠 and insert the number equal to their sum into 𝑠.\nFor example, if 𝑠={1,2,1,1,4,2,2} and you choose integers 2 and 2, then the multiset becomes {1,1,1,4,4,2}.\nYou win if the number 2048 belongs to your multiset. For example, if 𝑠={1024,512,512,4} you can win as follows: choose 512 and 512, your multiset turns into {1024,1024,4}. Then choose 1024 and 1024, your multiset turns into {2048,4} and you win.\nYou have to determine if you can win this game.\nYou have to answer 𝑞 independent queries.\nInput The first line contains one integer 𝑞 (1≤𝑞≤100) – the number of queries.\nThe first line of each query contains one integer 𝑛 (1≤𝑛≤100) — the number of elements in multiset.\nThe second line of each query contains 𝑛 integers 𝑠1,𝑠2,…,𝑠𝑛 (1≤𝑠𝑖≤229) — the description of the multiset. It is guaranteed that all elements of the multiset are powers of two.\nOutput For each query print YES if it is possible to obtain the number 2048 in your multiset, and NO otherwise.\nYou may print every letter in any case you want (so, for example, the strings yEs, yes, Yes and YES will all be recognized as positive answer).\nExample\n6 4 1024 512 64 512 1 2048 3 64 512 2 2 4096 4 7 2048 2 2048 2048 2048 2048 2048 2 2048 4096 YES YES NO NO YES YES Note In the first query you can win as follows: choose 512 and 512, and 𝑠 turns into {1024,64,1024}. Then choose 1024 and 1024, and 𝑠 turns into {2048,64} and you win. In the second query 𝑠 contains 2048 initially.\n解法： 统计数组中小于等于2048的数字，计算出sum，若sum\u0026gt;=2048,则肯定能够凑齐2048\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; long long s[110]; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); int n; while(t--){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); long long ans = 0; for(int i = 0; i \u0026lt; n; i++){ long long a; scanf(\u0026#34;%lld\u0026#34;, \u0026amp;a); if(a \u0026lt;= 2048) ans += a; } if(ans \u0026gt;= 2048) printf(\u0026#34;YES\\n\u0026#34;); else { printf(\u0026#34;NO\\n\u0026#34;); } } return 0; } B题：Knights 题目： a chess board with 𝑛 rows and 𝑛 columns. Initially all cells of the board are empty, and you have to put a white or a black knight into each cell of the board.\nA knight is a chess piece that can attack a piece in cell (𝑥2, 𝑦2) from the cell (𝑥1, 𝑦1) if one of the following conditions is met:\n|𝑥1−𝑥2|=2 and |𝑦1−𝑦2|=1, or |𝑥1−𝑥2|=1 and |𝑦1−𝑦2|=2. Here are some examples of which cells knight can attack. In each of the following pictures, if the knight is currently in the blue cell, it can attack all red cells (and only them). A duel of knights is a pair of knights of different colors such that these knights attack each other. You have to put a knight (a white one or a black one) into each cell in such a way that the number of duels is maximum possible.\nInput The first line contains one integer 𝑛 (3≤𝑛≤100) — the number of rows (and columns) in the board.\nOutput Print 𝑛 lines with 𝑛 characters in each line. The 𝑗-th character in the 𝑖-th line should be W, if the cell (𝑖, 𝑗) contains a white knight, or B, if it contains a black knight. The number of duels should be maximum possible. If there are multiple optimal answers, print any of them.\nExample 3 WBW BBB WBW Note In the first example, there are 8 duels: the white knight in (1, 1) attacks the black knight in (3, 2); the white knight in (1, 1) attacks the black knight in (2, 3); the white knight in (1, 3) attacks the black knight in (3, 2); the white knight in (1, 3) attacks the black knight in (2, 1); the white knight in (3, 1) attacks the black knight in (1, 2); the white knight in (3, 1) attacks the black knight in (2, 3); the white knight in (3, 3) attacks the black knight in (1, 2); the white knight in (3, 3) attacks the black knight in (2, 1).\n解法： WB交叉输出即可\n代码： #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++){ for(int j = 0; j \u0026lt; n; j++) { if((i + j) % 2 == 0) printf(\u0026#34;W\u0026#34;); else printf(\u0026#34;B\u0026#34;); } printf(\u0026#34;\\n\u0026#34;); } return 0; } C题 Perfect Team 题目： You may have already known that a standard ICPC team consists of exactly three members. The perfect team however has more restrictions. A student can have some specialization: coder or mathematician. She/he can have no specialization, but can\u0026rsquo;t have both at the same time.\nSo the team is considered perfect if it includes at least one coder, at least one mathematician and it consists of exactly three members.\nYou are a coach at a very large university and you know that 𝑐 of your students are coders, 𝑚 are mathematicians and 𝑥 have no specialization.\nWhat is the maximum number of full perfect teams you can distribute them into?\nNote that some students can be left without a team and each student can be a part of no more than one team.\nYou are also asked to answer 𝑞 independent queries.\nInput The first line contains a single integer 𝑞 (1≤𝑞≤104) — the number of queries.\nEach of the next 𝑞 lines contains three integers 𝑐, 𝑚 and 𝑥 (0≤𝑐,𝑚,𝑥≤108) — the number of coders, mathematicians and students without any specialization in the university, respectively.\nNote that the no student is both coder and mathematician at the same time.\nOutput Print 𝑞 integers — the 𝑖-th of them should be the answer to the 𝑖 query in the order they are given in the input. The answer is the maximum number of full perfect teams you can distribute your students into.\nExample 6 1 1 1 3 6 0 0 0 0 0 1 1 10 1 10 4 4 1 1 3 0 0 1 3 Note In the first example here are how teams are formed: 1.the only team of 1 coder, 1 mathematician and 1 without specialization; 2.all three teams consist of 1 coder and 2 mathematicians; 3.no teams can be formed; 4.no teams can be formed; 5.one team consists of 1 coder, 1 mathematician and 1 without specialization, the rest aren\u0026rsquo;t able to form any team; 6.one team consists of 1 coder, 1 mathematician and 1 without specialization, one consists of 2 coders and 1 mathematician and one consists of 1 coder and 2 mathematicians.\n解法： 首先统计sum，得到sum/3，即能分得队伍的最大值，然后取c,m的最小值，最后再取两个值中的最小值。\n代码： #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--){ long long a, b, c; scanf(\u0026#34;%lld%lld%lld\u0026#34;, \u0026amp;a, \u0026amp;b, \u0026amp;c); long long ans = (a +b + c)/3; long long p = min(a,b); ans = min(p, ans); printf(\u0026#34;%lld\\n\u0026#34;, ans); } return 0; } D题 题目： You have a fence consisting of 𝑛 vertical boards. The width of each board is 1. The height of the 𝑖-th board is 𝑎𝑖. You think that the fence is great if there is no pair of adjacent boards having the same height. More formally, the fence is great if and only if for all indices from 2 to 𝑛, the condition 𝑎𝑖−1≠𝑎𝑖 holds.\nUnfortunately, it is possible that now your fence is not great. But you can change it! You can increase the length of the 𝑖-th board by 1, but you have to pay 𝑏𝑖 rubles for it. The length of each board can be increased any number of times (possibly, zero).\nCalculate the minimum number of rubles you have to spend to make the fence great again!\nYou have to answer 𝑞 independent queries.\nInput The first line contains one integer 𝑞 (1≤𝑞≤3⋅10^5) — the number of queries.\nThe first line of each query contains one integers 𝑛 (1≤𝑛≤3⋅10^5) — the number of boards in the fence.\nThe following 𝑛 lines of each query contain the descriptions of the boards. The 𝑖-th line contains two integers 𝑎𝑖 and 𝑏𝑖 (1≤𝑎𝑖,𝑏𝑖≤10^9) — the length of the 𝑖-th board and the price for increasing it by 1, respectively.\nIt is guaranteed that sum of all 𝑛 over all queries not exceed 3⋅105.\nIt is guaranteed that answer to each query will not exceed 1018.\nOutput For each query print one integer — the minimum number of rubles you have to spend to make the fence great.\n###Example input\n3 3 2 4 2 1 3 5 3 2 3 2 10 2 6 4 1 7 3 3 2 6 1000000000 2 output\n2 9 0 Note In the first query you have to increase the length of second board by 2. So your total costs if 2⋅𝑏2=2.\nIn the second query you have to increase the length of first board by 1 and the length of third board by 1. So your total costs if 1⋅𝑏1+1⋅𝑏3=9.\nIn the third query the fence is great initially, so you don\u0026rsquo;t need to spend rubles.\n解法： 这个题后面补题做的(菜死了)。用dp[i][j]代表处理到i的位置时，增加j满足条件的最小值。 第二维数组大小只有3，因为在某一位置的数最多可能增加2个单位长度。\nif(a[i - 1] + j != a[i] + k) dp[i][k] = min(dp[i][k], dp[i - 1][j] + b[i] * k); 进行处理i时，与i-1进行比较，选择满足两个位置长度不同的时候，进行比较选择dp[i][k]的最小值。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; const int maxn = 300010; long long a[maxn], b[maxn]; long long dp[maxn][3]; int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--){ int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%lld%lld\u0026#34;, \u0026amp;a[i], \u0026amp;b[i]); for(int i = 0; i \u0026lt; n; i++) for(int j = 0; j \u0026lt; 3; j++) dp[i][j] = 1e18; for(int i = 0; i \u0026lt; 3; i++) dp[0][i] = b[0] * i; for(int i = 1; i \u0026lt; n; i++) for(int j = 0; j \u0026lt; 3; j++) for(int k = 0; k \u0026lt; 3; k++){ if(a[i - 1] + j != a[i] + k) dp[i][k] = min(dp[i][k], dp[i - 1][j] + b[i] * k); } long long ans = 1e18; for(int i = 0; i \u0026lt; 3; i++) ans = min(ans, dp[n - 1][i]); printf(\u0026#34;%lld\\n\u0026#34;, ans); } return 0; } ","permalink":"https://eonh1u.github.io/posts/cf-edu-73/","summary":"\u003cp\u003e昨天参加了cf—edu-73 div2。嗯 很菜 以后有时间多参加一下cf，提一下rating。\u003c/p\u003e\n\u003ch1 id=\"a题-2048-games\"\u003eA题 2048 Games：\u003c/h1\u003e\n\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eYou are playing a variation of game 2048. Initially you have a multiset 𝑠 of 𝑛 integers. Every integer in this multiset is a power of two.\u003c/p\u003e\n\u003cp\u003eYou may perform any number (possibly, zero) operations with this multiset.\u003c/p\u003e\n\u003cp\u003eDuring each operation you choose two equal integers from 𝑠, remove them from 𝑠 and insert the number equal to their sum into 𝑠.\u003c/p\u003e","title":"cf-edu-73"},{"content":"题目： N个整数组成的序列a[1],a[2],a[3],…,a[n]，从中选出一个子段（a[i],a[i+1],…a[j]），使这个子段的和\u0026gt;0，并且这个和是所有和\u0026gt;0的子序列中最小的。\n例如：4，-1，5，-2，-1，2，6，-2。-1，5，-2，-1，序列和为1，是最小的。\n输入 第1行：整数序列的长度N（2 \u0026lt;= N \u0026lt;= 50000) 第2 - N+1行：N个整数\n输出 输出最小正子段和。\n输入样例\n8 4 -1 5 -2 -1 2 6 -2 输出样例\n1 解法： 遍历数组处理前缀和，同时记录前缀和，在遍历到a[i]时，找到与sum[i]相差最小的位置k，并且使得sum[i] - sum[k] \u0026gt; 0 ，可以利用二分进行查找，总复杂度为nlogn。\n代码： #include\u0026lt;stdio.h\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int a[500010]; set\u0026lt;long long \u0026gt; z; set\u0026lt;long long \u0026gt; f; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); long long sum = 0, ans = 9999999999; for(int i = 0; i \u0026lt; n; i++) { sum += a[i]; long long p = 0; set\u0026lt;long long \u0026gt; ::iterator it ; if(sum \u0026lt; 0){ it = f.lower_bound(-sum); if(it != f.end()){ while(it != f.end() \u0026amp;\u0026amp; *it == -sum) it++; if(it == f.end()){ continue; } p = *it; } f.insert(-sum); } else{ it = z.lower_bound(-sum); if(it != z.end()){ while(it != z.end() \u0026amp;\u0026amp; *it == -sum) it++; if(it == z.end()){ continue; } p = *it; } z.insert(-sum); } // for(it = z.begin(); it != z.end(); it++) //printf(\u0026#34;%lld \u0026#34;, *it); // printf(\u0026#34;\\n%lld %lld\\n\u0026#34;, sum ,-p); if(sum + p \u0026gt; 0) ans = min(ans, sum + p); } printf(\u0026#34;%lld\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-1065-%E6%9C%80%E5%B0%8F%E6%AD%A3%E5%AD%97%E6%AE%B5%E5%92%8C/","summary":"\u003ch2 id=\"题目\"\u003e题目：\u003c/h2\u003e\n\u003cp\u003eN个整数组成的序列a[1],a[2],a[3],…,a[n]，从中选出一个子段（a[i],a[i+1],…a[j]），使这个子段的和\u0026gt;0，并且这个和是所有和\u0026gt;0的子序列中最小的。\u003c/p\u003e\n\u003cp\u003e例如：4，-1，5，-2，-1，2，6，-2。-1，5，-2，-1，序列和为1，是最小的。\u003c/p\u003e\n\u003ch3 id=\"输入\"\u003e输入\u003c/h3\u003e\n\u003cp\u003e第1行：整数序列的长度N（2 \u0026lt;= N \u0026lt;= 50000)\n第2 - N+1行：N个整数\u003c/p\u003e\n\u003ch3 id=\"输出\"\u003e输出\u003c/h3\u003e\n\u003cp\u003e输出最小正子段和。\u003c/p\u003e","title":"51nod-1065-最小正字段和"},{"content":"题目： 司令部的将军们打算在N*N的网格地图上部署他们的炮兵部队。一个N*N的地图由N行N列组成，地图的每一格可能是山地（用\u0026quot;X\u0026quot;表示），也可能是平原（用\u0026quot;.\u0026ldquo;表示）。在每一格平原地形上最多可以布置一支炮兵部队（山地上不能够部署炮兵部队）；一支炮兵部队在地图上的攻击范围是它所在位置的对应的行和列，但是大炮打出去之后如果被山地阻挡 了，那么攻击范围就到那块山地。\n现在，将军们规划如何部署炮兵部队，在防止误伤的前提下（保证任何两支炮兵部队之间不能互相攻击，即任何一支炮兵部队都不在其他支炮兵部队的攻击范围内），在整个地图区域内最多能够摆放多少我军的炮兵部队。\n样例解释：\n上图中显示的是相同的地图中不同的放置大炮的方案。黑方块表示山地，白方块表示平原，黑圆表示对应的平原放置了大炮。第一张图是不放大炮的情况。第二张图和第三张图是合理的放置大炮的方案。最后两张图是不合理的放置大炮的方案。 对于这个地图来讲，最多能放置5门大炮。第二张图就是一种最优的放置方案，当然还有其它的最优放置方案。\n输入 单组测试数据。 第一行有一个整数N(1\u0026lt;=N\u0026lt;=4)。 接下来N行，每行有N个字符（只有两种字符：\u0026rsquo;.\u0026rsquo; 表示平原， \u0026lsquo;X\u0026rsquo;表示山地）。 输出 输出一个整数表示答案。 输入样例 样例输入1 4 .X.. \u0026hellip;. XX.. \u0026hellip;. 输出样例 样例输出1 5 解法：因此数据极小，因此暴力每次情况即可，最终选取可放置数量最多的。 代码：\n#include\u0026lt;stdio.h\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int n; char c[5][5]; char s[5][5]; void change(int x) { for(int i = 0; i \u0026lt; n; i++) for(int j = 0; j \u0026lt; n; j++){ if(c[i][j] == \u0026#39;.\u0026#39;){ if(x\u0026amp;1) s[i][j] = \u0026#39;p\u0026#39;; else{ s[i][j] = \u0026#39;.\u0026#39;; } } else{ s[i][j] = \u0026#39;X\u0026#39;; } x \u0026gt;\u0026gt;= 1; } } bool isTrue() { for(int i = 0; i \u0026lt; n ;i++) { int now = 0; for(int j = 0; j \u0026lt; n; j++){ if(s[i][j] == \u0026#39;p\u0026#39;) now++; else if(s[i][j] == \u0026#39;X\u0026#39;){ now = 0; } if(now \u0026gt; 1) return false; } } for(int i = 0; i \u0026lt; n ;i++) { int now = 0; for(int j = 0; j \u0026lt; n; j++){ if(s[j][i] == \u0026#39;p\u0026#39;) now++; else if(s[j][i] == \u0026#39;X\u0026#39;){ now = 0; } if(now \u0026gt; 1) return false; } } return true; } int ans() { int num = 0; for(int i = 0; i \u0026lt; n; i++) for(int j = 0; j \u0026lt; n; j++) if(s[i][j] == \u0026#39;p\u0026#39;) num++; return num; } int main() { scanf(\u0026#34;%d\\n\u0026#34;, \u0026amp;n); char t; for(int i = 0; i \u0026lt; n ;i++){ for(int j = 0; j \u0026lt; n; j++) scanf(\u0026#34;%c\u0026#34;, \u0026amp;c[i][j]); scanf(\u0026#34;%c\u0026#34;, \u0026amp;t); } int now = 1; now \u0026lt;\u0026lt;= n*n+1; now--; //printf(\u0026#34;%d\\n\u0026#34;, now); int ANS = 0; while(now--) { change(now); if(isTrue()){ ANS = max(ANS, ans()); } } printf(\u0026#34;%d\\n\u0026#34;, ANS); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1919-%E7%82%AE%E5%85%B5%E9%98%B5%E5%9C%B0/","summary":"\u003cp\u003e题目：\n司令部的将军们打算在N*N的网格地图上部署他们的炮兵部队。一个N*N的地图由N行N列组成，地图的每一格可能是山地（用\u0026quot;X\u0026quot;表示），也可能是平原（用\u0026quot;.\u0026ldquo;表示）。在每一格平原地形上最多可以布置一支炮兵部队（山地上不能够部署炮兵部队）；一支炮兵部队在地图上的攻击范围是它所在位置的对应的行和列，但是大炮打出去之后如果被山地阻挡 了，那么攻击范围就到那块山地。\u003c/p\u003e","title":"51nod-1919-炮兵阵地"},{"content":"题目： 现在要在办公室里面安装监控， 由于预算有限，现在只能安装一个摄像头，这个摄像头是可以360度旋转的。现在就要选择一个位置安装这个摄像头，使得它能够监控到办公室中的所有地方。办公室的边界以多边形给出，这个多边的所有边都是平行于座标轴的，并且不自交。\n样例解释：\n左边的图对应的是第一个样例，把摄像头安装在点的位置就可以监控到所有的地方了，右边的图对应第二个样例，这个办公室没有办法找到一个地方安装摄像头使得所有地方都被监控到，如果安装在点的位置，灰色的部分就不能被监控到了。\n输入 单组测试数据。 第一行有一个整数n (4 \u0026lt;= n \u0026lt;= 100)，表示多边形的顶点数目。 接下来n行，每行出两个整数x 和 y（-100000\u0026lt;=x,y\u0026lt;=100000），表示多边形的顶点，以顺时针的方向给出。 所有的顶点都是不一样的。 输出 如果能够安装一个摄像头使得所有区域被监控到输出Yes，否则输出No。 输入样例 样例输入1 4 0 0 0 1 1 1 1 0\n样例输入2 8 0 0 0 2 1 2 1 1 2 1 2 2 3 2 3 0 输出样例 样例输出1 Yes 样例输出2 No 解法： 循环每条线段得到最终满足条件区域，最后判断区域是否为空即可 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; const int inf = 99999999; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); n--; int X,Y; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;X, \u0026amp;Y); int px = X, py = Y; int lx = -inf,rx = inf, ly = -inf, ry = inf; while(n--) { int x,y; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;x, \u0026amp;y); if(y \u0026lt; Y) rx= min(rx, X); if(y \u0026gt; Y) lx = max(lx, X); if(x \u0026gt; X) ry = min(ry, Y); if(x \u0026lt; X) ly = max(ly, Y); X = x; Y = y; } if(py \u0026lt; Y) rx= min(rx, X); if(py \u0026gt; Y) lx = max(lx, X); if(px \u0026gt; X) ry = min(ry, Y); if(px \u0026lt; X) ly = max(ly, Y); //printf(\u0026#34;%d %d %d %d\\n\u0026#34;, lx, rx, ly, ry); if(ly \u0026gt; ry || lx \u0026gt; rx) printf(\u0026#34;No\u0026#34;); else { printf(\u0026#34;Yes\u0026#34;); } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1942-%E5%AE%89%E8%A3%85%E7%9B%91%E6%8E%A7/","summary":"\u003cp\u003e题目：\n现在要在办公室里面安装监控， 由于预算有限，现在只能安装一个摄像头，这个摄像头是可以360度旋转的。现在就要选择一个位置安装这个摄像头，使得它能够监控到办公室中的所有地方。办公室的边界以多边形给出，这个多边的所有边都是平行于座标轴的，并且不自交。\u003c/p\u003e","title":"51nod-1942-安装监控"},{"content":"题目： 在二维平面上，给定两个矩形，满足矩形的每条边分别和坐标轴平行，求这个两个矩形的并的面积。即它们重叠在一起之后的总的面积。\n输入 8个数，分别表示第一个矩形左下角坐标为(A,B)，右上角坐标为(C,D)；第二个矩形左下角坐标为(E,F)，右上角坐标为(G,H)。 保证A\u0026lt;C，B\u0026lt;D，E\u0026lt;G，F\u0026lt;H。 保证所有数的绝对值不超过2*10^9，矩形并的面积≤2*10^9。\n输出 输出一个数表示矩阵并的面积。 输入样例 -3 0 3 4 0 -1 9 2 输出样例 45 解法：判断长与宽重合边长即可。 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; long long f(long long x1, long long x2, long long y1, long long y2) { if(x1 \u0026lt; y1) { if(y1 \u0026gt;= x2) return 0; else{ if(y2 \u0026gt;= x2) return x2 - y1; else return y2 - y1; } } else { if(x1 \u0026gt;= y2) return 0; else{ if(x2 \u0026gt;= y2) return y2 - x1; else { return x2 - x1; } } } } int main() { long long x[4],y[4]; for(int i = 0; i \u0026lt; 4; i++) scanf(\u0026#34;%lld%lld\u0026#34;, \u0026amp;x[i], \u0026amp;y[i]); long long X = f(x[0],x[1],x[2],x[3]); long long Y = f(y[0],y[1],y[2],y[3]); long long ans = (x[1] - x[0])* (y[1] - y[0]) + (x[3] - x[2])* (y[3] - y[2]) - X*Y; printf(\u0026#34;%lld\\n\u0026#34;, ans); } PS：最近一直在划水，做一些水题，慢慢提高难度吧。加油！！！\n","permalink":"https://eonh1u.github.io/posts/51nod-2488-%E7%9F%A9%E5%BD%A2%E9%9D%A2%E7%A7%AF%E5%B9%B6%E7%9A%84%E9%9D%A2%E7%A7%AF/","summary":"\u003cp\u003e题目：\n在二维平面上，给定两个矩形，满足矩形的每条边分别和坐标轴平行，求这个两个矩形的并的面积。即它们重叠在一起之后的总的面积。\u003c/p\u003e\n\u003cp\u003e输入\n8个数，分别表示第一个矩形左下角坐标为(A,B)，右上角坐标为(C,D)；第二个矩形左下角坐标为(E,F)，右上角坐标为(G,H)。\n保证A\u0026lt;C，B\u0026lt;D，E\u0026lt;G，F\u0026lt;H。\n保证所有数的绝对值不超过2*10^9，矩形并的面积≤2*10^9。\u003c/p\u003e","title":"51nod-2488-矩形面积并的面积"},{"content":"题目: 在网络中，发送一个包需要知道对方的物理地址，当不知道物理地趣的时候，就要向网络中广播发送对方的IP地址，然后每一台计算会收到这个广播，如果IP和自己的计算对上，就把自己的物理地址发送出去。 现在有n台计算，编号从1到n，现在1号计算向网络中发送广播，问经过多少时间后所有的计算机都会收到这个广播。\n输入的网络保证所有的计算机之间是可以相互通信的。\n输入 单组测试数据。 第一行有一个整数n(1 \u0026lt;= n \u0026lt;= 100)。 接下来输入一个邻接矩阵A，A的大小是n x n。里面的元素要么是一个非负整数，或者是一个字符x。如果A[i][j]是x那么第i台计算机和第j台计算机没有直接相连。否则表示信号在第i台计算机和第j台计算机之间传播需要A[i][j]的时间。 自己发给自己是不需要时间的所以对于所有的 1 \u0026lt;= i \u0026lt;= n，A[i][i] = 0。输入的网络是一个无向图，所以A[i][j] = A[j][i]。那么只需要输入矩阵的下三角部分即可。 那么接下来给出n-1行， 第一行有一个整数表示A[2][1]。 第二行有两个整数表示A[3][1]和A[3][2]。 。。。 第n-1行有n-1个整数A[n][1],A[n][2], A[n][3]\u0026hellip; A[n][n-1]。 0\u0026lt;=A[i][j]\u0026lt;=100。 输出 输出一个整数表示答案。 输入样例 样例输入1 5 50 30 5 100 20 50 10 x x 10 输出样例 样例输出1 35 解法：最短路裸题 代码：\n#include\u0026lt;stdio.h\u0026gt; #include\u0026lt;iostream\u0026gt; #include\u0026lt;algorithm\u0026gt; #include \u0026lt;cstdlib\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;cmath\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; struct Node { int to; long long len; bool operator\u0026lt;(const Node \u0026amp;a) const { return len \u0026gt; a.len; } }; bool isUsed[510]; long long ans[510]; vector\u0026lt;Node\u0026gt; NodeQueue[510]; void addEdge(int s, int e, int len) { NodeQueue[s].push_back((Node){e,len}); NodeQueue[e].push_back((Node){s,len}); } int n; priority_queue\u0026lt;Node\u0026gt; PriNodeQueue; int main() { scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 2; i \u0026lt;= n; i++) for(int j = 1; j \u0026lt; i; j++){ string s; cin \u0026gt;\u0026gt; s; if(s != \u0026#34;x\u0026#34;){ int len = atoi(s.c_str()); //printf(\u0026#34;%d\\n\u0026#34;, len); addEdge(i,j,len); } } for(int i = 0; i \u0026lt; 505; i++) ans[i] = 999999999999; ans[1] = 0; PriNodeQueue.push((Node){1,0}); while(!PriNodeQueue.empty()){ Node now = PriNodeQueue.top(); PriNodeQueue.pop(); int u = now.to; if(!isUsed[u]){ isUsed[u] = true; for(int i = 0; i \u0026lt; NodeQueue[u].size(); i++){ if(!isUsed[NodeQueue[u][i].to]){ int v = NodeQueue[u][i].to; int len = NodeQueue[u][i].len; if(ans[v] \u0026gt; ans[u] + len) { ans[v] = ans[u] + len; PriNodeQueue.push((Node){v,ans[v]}); } } } } } long long a = 0; for(int i = 1; i \u0026lt;= n; i++){ //printf(\u0026#34;%d\\n\u0026#34;, ans[i]); a = max(a, ans[i]); } printf(\u0026#34;%lld\u0026#34;, a); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1593-%E7%89%A9%E7%90%86%E5%9C%B0%E5%9D%80%E6%9F%A5%E8%AF%A2/","summary":"\u003cp\u003e题目:\n在网络中，发送一个包需要知道对方的物理地址，当不知道物理地趣的时候，就要向网络中广播发送对方的IP地址，然后每一台计算会收到这个广播，如果IP和自己的计算对上，就把自己的物理地址发送出去。\n现在有n台计算，编号从1到n，现在1号计算向网络中发送广播，问经过多少时间后所有的计算机都会收到这个广播。\u003c/p\u003e\n\u003cp\u003e输入的网络保证所有的计算机之间是可以相互通信的。\u003c/p\u003e","title":"51nod-1593-物理地址查询"},{"content":"题目： 问题描述 面对夜市上琳琅满目的美食, 吃货 Alice 正在犯难. 夜市上有 n 种食物. 每种都是不可分割地一份一份出售的. Alice 是一个珍惜食物的好孩子(吃货), 所以买到的食物她都会吃完不浪费. Alice 当然想尝试尽量多不同的的美味, 所以同一种食物她不会重复购买, 即最多只会买一份. 每份食物都有一个营养价值和美味指数. Alice当然想吃得又健康又美味, 所以她今晚的目标就是所吃食物的营养价值总和不能少于x, 而美味指数总和不能少于y. 精明的 Alice 当然想省下钱来明天再吃一顿, 所以她想花最少的钱实现她的目标.\n所以 Alice 来求助同班的天才程序员 Bob, 就是你啦. 她告诉你 n 种食物的营养价值, 美味指数和价格, 以及她的目标 x 和 y. 你要告诉她最少要花多少钱才能达到目标.\n输入 从标准文件输入, 第一行包括两个整数x和y, 由一个空格隔开(1\u0026lt;=x\u0026lt;=21,1\u0026lt;=y\u0026lt;=79)，表示 Alice 今晚的营养目标和美味目标。第二行包括一个整数n(1\u0026lt;=n\u0026lt;=1000)表示可选择的食物数量. 以下n行包括每种食物的描述：第i+2行包括三个整数xi、yi、pi,(1\u0026lt;=xi\u0026lt;=21,1\u0026lt;=yi\u0026lt;=79,1\u0026lt;=pi\u0026lt;=800)，分别为该种食物的营养价值, 美味指数和价格.\n输出 你的程序应该输出一个整数，表示所选食物的最小总价格, 且其营养价值总和不小于x, 美味指数总和不小于y.\n输入样例 5 60 5 3 36 120 10 25 129 5 50 250 1 45 130 4 20 119 输出样例 249 题解：01背包的变形，dp[i][j]代表营养价值为i，美味指数为j时的最小价格，因为必须满足营养价值与美味指数的要求，因此在状态转移时，dp[i][j]必须是有实际意义的值，因为x\u0026lt;=21 y\u0026lt;=79，因此dp数组的大小最多为dp[221][279],循环得到dp的值之后，选取最优的解即可。 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; int dp[55][205]; int xi[1010]; int yi[1010]; int pi[1010]; int main() { int x,y; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;x, \u0026amp;y); int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) { scanf(\u0026#34;%d%d%d\u0026#34;, \u0026amp;xi[i], \u0026amp;yi[i], \u0026amp;pi[i]); } for(int i = 0; i \u0026lt; 50; i++) for(int j = 0; j \u0026lt; 200; j++) dp[i][j] = 99999999; dp[0][0] = 0; for(int i = 0; i \u0026lt; n; i++){ for(int x = 50; x - xi[i] \u0026gt;= 0; x--){ for(int y = 200; y - yi[i] \u0026gt;= 0; y--){ if(dp[x-xi[i]][y-yi[i]] != 99999999){ dp[x][y] = min(dp[x][y], dp[x-xi[i]][y-yi[i]] + pi[i]); } } } } int ans = 99999999; for(int i = x; i \u0026lt; 50; i++) for(int j = y; j \u0026lt; 200; j++) ans = min(ans, dp[i][j]); printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/ucas-alice-s-food/","summary":"\u003cp\u003e题目：\n问题描述\n面对夜市上琳琅满目的美食, 吃货 Alice 正在犯难. 夜市上有 n 种食物. 每种都是不可分割地一份一份出售的. Alice 是一个珍惜食物的好孩子(吃货), 所以买到的食物她都会吃完不浪费. Alice 当然想尝试尽量多不同的的美味, 所以同一种食物她不会重复购买, 即最多只会买一份. 每份食物都有一个营养价值和美味指数. Alice当然想吃得又健康又美味, 所以她今晚的目标就是所吃食物的营养价值总和不能少于x, 而美味指数总和不能少于y. 精明的 Alice 当然想省下钱来明天再吃一顿, 所以她想花最少的钱实现她的目标.\u003c/p\u003e","title":"ucas Alice's Food"},{"content":"给定一个字符串S，只由k种小写字母组成。现在给定一个长度L，要求统计一下S有多少种不同的长度为L的子段(S中连续的几个字符)。\n输入 单组测试数据。 第一行两个整数L和k。（L\u0026gt;=1，1\u0026lt;=k\u0026lt;=26,k^L\u0026lt;=2*10^7） 第二行一个字符串S。（1\u0026lt;=|S|\u0026lt;=1000000） 输出 输出一个整数表示答案。\n输入样例 1 2 ababab 输出样例 2 解法：暴力即可 代码：\n#include\u0026lt;iostream\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;set\u0026gt; using namespace std; set\u0026lt;string\u0026gt; S; int main() { int l, k; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;l, \u0026amp;k); string s; cin \u0026gt;\u0026gt; s; for(int i = 0; i \u0026lt;= s.length() - l; i++){ string s1 = s.substr(i, l); S.insert(s1); } printf(\u0026#34;%lld\\n\u0026#34;, S.size()); } ","permalink":"https://eonh1u.github.io/posts/1906-%E5%AD%97%E6%AE%B5%E7%BB%9F%E8%AE%A1/","summary":"\u003cp\u003e给定一个字符串S，只由k种小写字母组成。现在给定一个长度L，要求统计一下S有多少种不同的长度为L的子段(S中连续的几个字符)。\u003c/p\u003e\n\u003cp\u003e输入\n单组测试数据。\n第一行两个整数L和k。（L\u0026gt;=1，1\u0026lt;=k\u0026lt;=26,k^L\u0026lt;=2*10^7）\n第二行一个字符串S。（1\u0026lt;=|S|\u0026lt;=1000000）\n输出\n输出一个整数表示答案。\u003c/p\u003e","title":"1906-字段统计"},{"content":"题目： 现在大多数的文本编辑器都的单词究错功能，即你输入的单词不能够在词典中找到的话，他就会建议你修改，然后给出几个候选项。\n现在我们就要来写一个生成候选项的算法。\n具体算法是这样的，如果输入的单词能够在字典中找到，那么就不用推荐，否则就在字典中找那些能够通过修改一个字母得到目标单词的选项作为推荐。\n修改一个字母包括删除一个字母，添加一个字母，以及把单词中的某个位置的字母进行替换。\n输入 单组测试数据。 前面若干行给出字典中的单词，每行一个，遇到\u0026quot;#\u0026ldquo;表示字典中的单词输入结束。 接下来若干行给出用户输入的单词，每行一个，遇到\u0026rdquo;#\u0026ldquo;结束。 字典中单词不超过15000个。用户输入的单词不超过60个。每个单词只由小写字母组成，并且非空，长度不超过20。 输出 对于每一个用户的输入，如果在字典中能够找到就输出 \u0026ldquo;单词 is correct\u0026rdquo;。否则就输出\u0026quot;单词: 候选1 候选2 \u0026hellip;\u0026quot;,候选项按照输入的顺序进行排列。如果找不到候选项，则输出\u0026quot;单词:”。具体可参见样例。 输入样例 样例输入1 i has be more me if ^# me m contest oo i ^# 输出样例 样例输出1 me is correct m: i me contest: oo: i is correct 解法: 关键在于如何进行单词匹配，长度相差大于1的可以直接判断为false，长度相差为1的进行处理时，当出现字符不匹配时，选择进行一次删除或者添加操作(效果相同)，长度相同时直接一次判断即可。 代码：\n#include\u0026lt;iostream\u0026gt; #include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;set\u0026gt; using namespace std; set\u0026lt;string\u0026gt; dict; set\u0026lt;string\u0026gt; words; string s[15010]; bool isTrue(string a, string b) { int la = a.length(), lb = b.length(); if(abs(la - lb) \u0026gt; 1) return false; if(la == lb){ int sum = 0; for(int i = 0; i \u0026lt; la; i++){ if(a[i] != b[i]) sum++; if(sum \u0026gt; 1) return false; } } else{ int sum = 0; if(lb \u0026gt; la) swap(a, b); int i = 0 ,j = 0; for(int k = 0; k \u0026lt; lb; k++) { if(a[i++] != b[j++]){ sum++; if(sum == 2) return false; j--;lb++; } } } return true; } int main() { int now = 0 ,sum = 0; string str; while(cin\u0026gt;\u0026gt;str) { if(str == \u0026#34;#\u0026#34;){ now++; if(now == 2) break; continue; } if(now == 0){ dict.insert(str); s[sum++] = str; } else{ if(dict.find(str) != dict.end()){ cout \u0026lt;\u0026lt; str; printf(\u0026#34; is correct\\n\u0026#34;); } else{ cout \u0026lt;\u0026lt; str \u0026lt;\u0026lt; \u0026#34;:\u0026#34;; for(int i = 0; i \u0026lt; sum; i++){ if(isTrue(str,s[i])) cout\u0026lt;\u0026lt;\u0026#34; \u0026#34;\u0026lt;\u0026lt; s[i]; } cout\u0026lt;\u0026lt;endl; } } } } ","permalink":"https://eonh1u.github.io/posts/1880-%E5%8D%95%E8%AF%8D%E7%BA%A0%E9%94%99/","summary":"\u003cp\u003e题目：\n现在大多数的文本编辑器都的单词究错功能，即你输入的单词不能够在词典中找到的话，他就会建议你修改，然后给出几个候选项。\u003c/p\u003e\n\u003cp\u003e现在我们就要来写一个生成候选项的算法。\u003c/p\u003e\n\u003cp\u003e具体算法是这样的，如果输入的单词能够在字典中找到，那么就不用推荐，否则就在字典中找那些能够通过修改一个字母得到目标单词的选项作为推荐。\u003c/p\u003e\n\u003cp\u003e修改一个字母包括删除一个字母，添加一个字母，以及把单词中的某个位置的字母进行替换。\u003c/p\u003e","title":"51nod-1880-单词纠错"},{"content":"Problem Description Recall the problem of finding the number of inversions. As in the course, we are given a sequence of nn numbers a1,a2,⋯,ana1,a2,⋯,an, and we define an inversion to be a pair i\u0026lt;jiajai\u0026gt;aj.\nWe motivated the problem of counting inversions as a good measure of how different two orderings are. However, one might feel that this measure is too sensitive. Let\u0026rsquo;s call a pair a significant inversion if i\u0026lt;ji3ajai\u0026gt;3aj. Give an O(nlogn)O(nlog⁡n) algorithm to count the number of significant inversions between two orderings.\nThe array contains N elements (1\u0026lt;=N\u0026lt;=100,000). All elements are in the range from 1 to 1,000,000,000.\nInput The first line contains one integer N, indicating the size of the array. The second line contains N elements in the array.\n50% test cases guarantee that N \u0026lt; 1000. Output Output a single integer which is the number of pairs of significant inversions.\nSample Inout 6 13 8 5 3 2 1 Sample Output 6 解法:标准的逆序对数上加了一点变化，ai\u0026gt;aj*3 才算做逆序对数，因此在merge之前扫一遍就行计算逆序对的数量，然后加起来，将merge与计算逆序对数分开。 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; long long t[100010]; long long a[100010]; long long sum=0; void solve(int l,int r) { //printf(\u0026#34;%d %d\\n\u0026#34;,l,r); if(r-l\u0026lt;2) { if(r - l == 1 \u0026amp;\u0026amp; a[l] \u0026gt; 3 * a[r]) sum++; if(r-l == 1 \u0026amp;\u0026amp; a[l] \u0026gt; a[r]){ swap(a[l], a[r]); } return ; } int m = (l + r) \u0026gt;\u0026gt; 1; solve(l , m); solve(m+1 , r); int now = m-l+1; int sz = l, sy = m+1; int i = m, j = r; while (i \u0026gt;= l \u0026amp;\u0026amp; j \u0026gt; m) { if(a[i] \u0026gt; (long long) 3 * a[j]) { sum += j - m; i--; }else{ j--; } } for(int i = 0; i \u0026lt; r - l + 1; i++) { if(sz \u0026lt;= m \u0026amp;\u0026amp; sy \u0026lt;= r) { if(a[sz] \u0026gt; a[sy]){ t[i] = a[sy]; sy++; //sum += now; } else { t[i] = a[sz]; sz++; now--; } } else if(sz == m+1) { while(sy \u0026lt;= r) { t[i] = a[sy]; sy++; i++; } } else { while(sz \u0026lt;= m) { t[i] = a[sz]; sz++; i++; } } } for(int i= l ; i \u0026lt;= r; i++) a[i] = t[i-l]; } int main() { int n; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); for(int i = 1; i \u0026lt;=n; i++) scanf(\u0026#34;%lld\u0026#34;,\u0026amp;a[i]); solve(1,n); printf(\u0026#34;%lld\\n\u0026#34;,sum); return 0; } ","permalink":"https://eonh1u.github.io/posts/%E9%80%86%E5%BA%8F%E5%AF%B9%E6%95%B0%E5%8F%98%E5%BD%A2/","summary":"\u003cp\u003eProblem Description\nRecall the problem of finding the number of inversions. As in the course, we are given a sequence of nn numbers a1,a2,⋯,ana1,a2,⋯,an, and we define an inversion to be a pair i\u0026lt;ji\u003cj such that ai\u003eajai\u0026gt;aj.\u003c/p\u003e","title":"逆序对数变形"},{"content":"今天在ucas oj上面尝试做了两道题\nriver：二分即可 Description Two lovely frogs Alice and Bob live by a river. There are several stones in this river. Every morning, they will go to the other side of the river to have fun. They cross the river by jumping from one stone to another. One day, Alice decides to play tricks on Bob. She plans to remove some stones so that there is no “easy jump” for Bob to across the river any more. But she has no idea which stones she should remove. She needs your help.\nThe width of the river is an integer L((1≤L≤1,000,000,000). We treat the river as a one-dimensional line segment,with two endpoints A (two frog’s home) and B (the other side of the river). Among the river, there are N stones (0≤N≤50,000). The distance from the i-th stone to side A is Di (0\u0026lt;Di\u0026lt;L). Alice would like to remove M stones in the river (0≤M≤N) so that with the rest of the stones, the minimum distance among all possible jumps for Bob is the largest.\nInput Each instance contains two lines. The first line contains three integers L, N and M. The second line gives the positions of N stones. No two stones share the same position.\n30% test cases guarantee that N \u0026lt; 20. Output For each instance, output a single line with a single integer which is the maximum of the minimum distance among all possible jumps after removing M stones. In the example, Alice should remove stones with distance 2 and 14. After removing these two stones, the minimum distance of jumps is 4, and there are two jumps with distance 4: from 17 to 21, and from 21 to 25.\nSample Input 25 5 2 2 14 11 21 17 Sample Output 4 代码:\n#include\u0026lt;algorithm\u0026gt; using namespace std; int a[50010]; int L,n,k; bool c(int x) { int now = 0; int p = 0; for(int i = 0; i \u0026lt;= n; i++) { if(a[i] - now \u0026gt;= x) { now = a[i]; } else { p++; if(p \u0026gt; k) return false; } } return true; } int main() { scanf(\u0026#34;%d%d%d\u0026#34;, \u0026amp;L, \u0026amp;n, \u0026amp;k); for(int i = 0; i \u0026lt; n; i++){ scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); } a[n] = L; sort(a, a + n + 1); int l = 1, r = L; for(int i = 0; i \u0026lt; 200; i++) { //printf(\u0026#34;%d %d\\n\u0026#34;, l, r); int m = (l + r)/2; if(c(m)) l = m; else r = m -1; } if(c(r)) printf(\u0026#34;%d\\n\u0026#34;, r); else { printf(\u0026#34;%d\\n\u0026#34;, l); } return 0; } Longest Ordered Subsequence: nlogn Description A numeric sequence of aiai is ordered if a1\u0026lt;a2\u0026lt;⋯\u0026lt;aNa1\u0026lt;a2\u0026lt;⋯\u0026lt;aN. Let the subsequence of the given numeric sequence (a1,a2,…,aN)(a1,a2,…,aN) be any sequence (ai1,ai2,\u0026hellip;,aiK)(ai1,ai2,\u0026hellip;,aiK), where 1\u0026lt;=i1\u0026lt;i2\u0026lt;⋯\u0026lt;iK\u0026lt;=N1\u0026lt;=i1\u0026lt;i2\u0026lt;⋯\u0026lt;iK\u0026lt;=N. For example, sequence (1,7,3,5,9,4,8)(1,7,3,5,9,4,8) has ordered subsequences, e. g., (1,7)(1,7), (3,4,8)(3,4,8) and many others. All longest ordered subsequences are of length 44, e. g., (1,3,5,8)(1,3,5,8).\nYour program, when given the numeric sequence, must find the length of its longest ordered subsequence.\nInput The first line of input contains the length of sequence N. The second line contains the elements of sequence - N integers in the range from 0 to 10000 each, separated by spaces. 1 \u0026lt;= N \u0026lt;= 1000. But there is one test case with N = 1000000.\nOutput Output file must contain a single integer - the length of the longest ordered subsequence of the given sequence.\nSample Input 7 1 7 3 5 9 4 8 Sample Output 4 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; const int MAX = 1000010; int a[MAX]; int dp[MAX]; int inf = 99999999; int n; void solve() { fill(dp, dp + n, inf); for(int i = 0; i \u0026lt; n; i++) { *lower_bound(dp, dp + n, a[i]) = a[i]; } printf(\u0026#34;%d\\n\u0026#34;, lower_bound(dp, dp + n, inf) - dp); } int main() { scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); solve(); return 0; } ","permalink":"https://eonh1u.github.io/posts/ucas-river-and-longest-ordered-subsequence/","summary":"\u003cp\u003e今天在ucas oj上面尝试做了两道题\u003c/p\u003e\n\u003ch1 id=\"river二分即可\"\u003eriver：二分即可\u003c/h1\u003e\n\u003cp\u003eDescription\nTwo lovely frogs Alice and Bob live by a river. There are several stones in this river. Every morning, they will go to the other side of the river to have fun. They cross the river by jumping from one stone to another. One day, Alice decides to play tricks on Bob. She plans to remove some stones so that there is no “easy jump” for Bob to across the river any more. But she has no idea which stones she should remove. She needs your help.\u003c/p\u003e","title":"ucas river and Longest Ordered Subsequence"},{"content":"题目: 小b有一个01序列A，她想知道A有多少个非空连续子序列和为S。\n你能帮帮她吗？\n输入 第一行输入一个数n，表示A的长度； 第二行输入n个数‘0’或‘1’，表示A中的元素，以空格隔开； 第三行输入一个非负整数S； 其中0≤S≤n≤30000。\n输出 输出一个数，表示子数组的个数 输入样例 5 1 0 1 0 1 2 解法: 统计每个1之前0的个数即可，然后组合计算一下乘积，注意处理S为0的情况。 代码:\nusing namespace std; int sum[30010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int now = 0; int l = 0; for(int i = 0;i \u0026lt; n; i++) { int s; scanf(\u0026#34;%d\u0026#34;, \u0026amp;s); if(s == 0){ now++; } else{ sum[l++] = now; now = 0; } } sum[l] = now; int s; scanf(\u0026#34;%d\u0026#34;, \u0026amp;s); long long ans = 0; if(s \u0026gt; 0){ for(int i = 0; i + s \u0026lt;= l; i++) { ans += (sum[i] + 1) * (sum[i + s] + 1); } } else{ for(int i = 0; i \u0026lt;= l; i++){ //printf(\u0026#34;%d\\n\u0026#34;, sum[i]); ans += sum[i] *(sum[i] + 1)/2; } } printf(\u0026#34;%lld\u0026#34;, ans); return 0; } ","permalink":"https://eonh1u.github.io/posts/2518-%E5%92%8C%E4%B8%BAs/","summary":"\u003cp\u003e题目:\n小b有一个01序列A，她想知道A有多少个非空连续子序列和为S。\u003c/p\u003e\n\u003cp\u003e你能帮帮她吗？\u003c/p\u003e\n\u003cp\u003e输入\n第一行输入一个数n，表示A的长度；\n第二行输入n个数‘0’或‘1’，表示A中的元素，以空格隔开；\n第三行输入一个非负整数S；\n其中0≤S≤n≤30000。\u003c/p\u003e","title":"2518-和为S"},{"content":"题目： 你在一个二维空间里的(𝑥𝑀𝑒,𝑦𝑀𝑒)位置，你的家在(𝑥𝐻𝑜𝑚𝑒,𝑦𝐻𝑜𝑚𝑒)位置。每一秒钟你可以选择从你当前位置向上下左右四个方向之一移动一个单位。你现在归心似箭，觉得这么走很慢，所幸你有技能“凌波微步”，在这片二维空间中，有3对传送门，每一对传送门以(𝑥𝑠,𝑦𝑠,𝑥𝑡,𝑦𝑡)的形式给出，表示你到达(𝑥𝑠,𝑦𝑠)点就可以发动“凌波微步”技能，花费10秒钟到达(𝑥𝑡,𝑦𝑡)点，相反你也可以花费10秒钟从(𝑥𝑡,𝑦𝑡)点发动“凌波微步”技能到达(𝑥𝑠,𝑦𝑠)点。“凌波微步”技能可以无限多次发动，但只能在所给出的3对传送门之间使用。请问你回家最短用时多少秒。\n输入 输入第一行4个整数，依次是xMe、yMe、xHome、yHome，表示当前你的位置和你家的位置。 接下来三行，每行描述一对传送门(xs, ys, xt, yt)，含义见题面（0 \u0026lt;= xi, yi \u0026lt;= 10^9） 输出 输出仅一行，包含一个整数表示回家的最少用时 输入样例 0 0 20 20 1 1 18 20 1000 1003 1000 1004 1000 1005 1000 1006 输出样例 14 解法: 最短路径的一个变形，就坐标映射为点就可以 代码:\n#include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;vector\u0026gt; #include\u0026lt;map\u0026gt; using namespace std; struct Node { int to; long long len; bool operator\u0026lt;(const Node \u0026amp;a) const { return len \u0026gt; a.len; } }; struct xy { int x; int y; bool operator\u0026lt;(const xy \u0026amp;a) const { if(x == a.x) return y \u0026lt; a.y; else { return x \u0026lt; a.x; } } }; bool isUsed[510]; long long ans[510]; vector\u0026lt;Node\u0026gt; NodeQueue[510]; void addEdge(int s, int e, int len) { NodeQueue[s].push_back((Node){e,len}); NodeQueue[e].push_back((Node){s,len}); } map\u0026lt;xy,int\u0026gt; m; priority_queue\u0026lt;Node\u0026gt; PriNodeQueue; int main() { int sum = 0; int xme, yme, xhome, yhome; scanf(\u0026#34;%d%d%d%d\u0026#34;, \u0026amp;xme, \u0026amp;yme, \u0026amp;xhome, \u0026amp;yhome); m[(xy){xme,yme}] = sum++; m[(xy){xhome,yhome}] = sum++; addEdge(0,1,abs(xme-xhome) + abs(yme - yhome)); for(int i = 1; i \u0026lt; 4; i++) { int x1,y1,x2,y2; scanf(\u0026#34;%d%d%d%d\u0026#34;, \u0026amp;x1, \u0026amp;y1, \u0026amp;x2, \u0026amp;y2); map\u0026lt;xy,int\u0026gt; :: iterator it; if(m.find((xy){x1,y1}) == m.end()){ sum++; for(it = m.begin(); it != m.end(); it++) { int v = (*it).second; addEdge(sum,v,abs(x1-(*it).first.x) + abs(y1-(*it).first.y)); } m[(xy){x1,y1}] = sum; } if(m.find((xy){x2,y2}) == m.end()) { sum++; for(it = m.begin(); it != m.end(); it++) { int v = (*it).second; addEdge(sum,v,abs(x2-(*it).first.x) + abs(y2-(*it).first.y)); } m[(xy){x2,y2}] = sum; } int l = abs(x1-x2) + abs(y1-y2); addEdge(m[(xy){x1,y1}],m[(xy){x2,y2}],min(10,l)); } for(int i = 0; i \u0026lt; 10; i++) ans[i] = 9999999999; ans[0] = 0; PriNodeQueue.push((Node){0,0}); while(!PriNodeQueue.empty()){ Node now = PriNodeQueue.top(); PriNodeQueue.pop(); int u = now.to; if(!isUsed[u]){ isUsed[u] = true; // printf(\u0026#34;%d %d\\n\u0026#34;,u,ans[u]); for(int i = 0; i \u0026lt; NodeQueue[u].size(); i++){ if(!isUsed[NodeQueue[u][i].to]){ int v = NodeQueue[u][i].to; int len = NodeQueue[u][i].len; if(ans[v] \u0026gt; ans[u] + len) { ans[v] = ans[u] + len; PriNodeQueue.push((Node){v,ans[v]}); } } } } } printf(\u0026#34;%lld\u0026#34;,ans[1]); return 0; } ","permalink":"https://eonh1u.github.io/posts/2678-%E5%87%8C%E6%B3%A2%E5%BE%AE%E6%AD%A5/","summary":"\u003cp\u003e题目：\n你在一个二维空间里的(𝑥𝑀𝑒,𝑦𝑀𝑒)位置，你的家在(𝑥𝐻𝑜𝑚𝑒,𝑦𝐻𝑜𝑚𝑒)位置。每一秒钟你可以选择从你当前位置向上下左右四个方向之一移动一个单位。你现在归心似箭，觉得这么走很慢，所幸你有技能“凌波微步”，在这片二维空间中，有3对传送门，每一对传送门以(𝑥𝑠,𝑦𝑠,𝑥𝑡,𝑦𝑡)的形式给出，表示你到达(𝑥𝑠,𝑦𝑠)点就可以发动“凌波微步”技能，花费10秒钟到达(𝑥𝑡,𝑦𝑡)点，相反你也可以花费10秒钟从(𝑥𝑡,𝑦𝑡)点发动“凌波微步”技能到达(𝑥𝑠,𝑦𝑠)点。“凌波微步”技能可以无限多次发动，但只能在所给出的3对传送门之间使用。请问你回家最短用时多少秒。\u003c/p\u003e","title":"凌波微步"},{"content":"最短路径的裸题，用了nlogn的写法，优先队列，好久没写代码了，中间没bug出乎我的意料，以后每天一题不会落下，加油！\n代码：\n#include\u0026lt;algorithm\u0026gt; #include\u0026lt;cmath\u0026gt; #include\u0026lt;queue\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; struct Node { int to; long long len; bool operator\u0026lt;(const Node \u0026amp;a) const { return len \u0026gt; a.len; } }; bool isUsed[510]; long long ans[510]; vector\u0026lt;Node\u0026gt; NodeQueue[510]; void addEdge(int s, int e, int len) { NodeQueue[s].push_back((Node){e,len}); NodeQueue[e].push_back((Node){s,len}); } int n,m; priority_queue\u0026lt;Node\u0026gt; PriNodeQueue; int main() { scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;n, \u0026amp;m); while(m--) { int s, e, len; scanf(\u0026#34;%d%d%d\u0026#34;,\u0026amp;s, \u0026amp;e, \u0026amp;len); if(s != e) addEdge(s, e, len); } int s, t; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;s, \u0026amp;t); for(int i = 0; i \u0026lt; 505; i++) ans[i] = 999999999999; ans[s] = 0; PriNodeQueue.push((Node){s,0}); while(!PriNodeQueue.empty()){ Node now = PriNodeQueue.top(); PriNodeQueue.pop(); int u = now.to; if(!isUsed[u]){ isUsed[u] = true; for(int i = 0; i \u0026lt; NodeQueue[u].size(); i++){ if(!isUsed[NodeQueue[u][i].to]){ int v = NodeQueue[u][i].to; int len = NodeQueue[u][i].len; if(ans[v] \u0026gt; ans[u] + len) { ans[v] = ans[u] + len; PriNodeQueue.push((Node){v,ans[v]}); } } } } } printf(\u0026#34;%lld\u0026#34;,ans[t]); return 0; } ","permalink":"https://eonh1u.github.io/posts/2673-%E6%9C%80%E7%9F%AD%E8%B7%AF%E5%BE%84/","summary":"\u003cp\u003e最短路径的裸题，用了nlogn的写法，优先队列，好久没写代码了，中间没bug出乎我的意料，以后每天一题不会落下，加油！\u003c/p\u003e","title":"2673-最短路径"},{"content":"题目: 2656 阿克曼函数 1.0 秒 131,072.0 KB 5 分 1级题 阿克曼（Arkmann）函数 𝐴(𝑚,𝑛) 中，m与n的定义域是非负整数且本题中m\u0026lt;=3，n\u0026lt;=30。\n函数的定义为： 𝑎𝑘𝑚(𝑚,𝑛)=⎧⎩⎨⎪⎪𝑛+1𝑎𝑘𝑚(𝑚−1,1)𝑎𝑘𝑚(𝑚−1,𝑎𝑘𝑚(𝑚,𝑛−1))(𝑚=0)(𝑚\u0026gt;0,𝑛=0)(𝑚\u0026gt;0,𝑛\u0026gt;0)\n输入 两个整数 m n 输出 一个整数，akm(m,n)的结果 输入样例 1 1 输出样例 3 解法：递归记忆化即可，注意数组范围，数组的大小 代码:\nusing namespace std; int a[13][1000000]; int f(int m,int n) { if(a[m][n] != 0){ return a[m][n]; } if(m == 0) return a[m][n] = n + 1; else if(n == 0) return a[m][n] = f(m - 1, 1); else if(m \u0026gt; 0 \u0026amp;\u0026amp; n \u0026gt; 0) return a[m][n] = f(m - 1,f(m,n - 1)); } int main() { int n,m; scanf(\u0026#34;%d%d\u0026#34;,\u0026amp;n, \u0026amp;m); printf(\u0026#34;%d\u0026#34;,f(n,m)); } ","permalink":"https://eonh1u.github.io/posts/51nod-2562-%E9%98%BF%E5%85%8B%E6%9B%BC%E5%87%BD%E6%95%B0/","summary":"\u003cp\u003e题目:\n2656 阿克曼函数\n1.0 秒  131,072.0 KB 5 分 1级题\n阿克曼（Arkmann）函数 𝐴(𝑚,𝑛) 中，m与n的定义域是非负整数且本题中m\u0026lt;=3，n\u0026lt;=30。\u003c/p\u003e\n\u003cp\u003e函数的定义为：\n𝑎𝑘𝑚(𝑚,𝑛)=⎧⎩⎨⎪⎪𝑛+1𝑎𝑘𝑚(𝑚−1,1)𝑎𝑘𝑚(𝑚−1,𝑎𝑘𝑚(𝑚,𝑛−1))(𝑚=0)(𝑚\u0026gt;0,𝑛=0)(𝑚\u0026gt;0,𝑛\u0026gt;0)\u003c/p\u003e","title":"51nod-2562-阿克曼函数"},{"content":"题目: 有一个字符串S，长度为n，现在要对其作变换。变换的规则如下：对于第i（1\u0026lt;=i\u0026lt;=n）个字符，可以保持不变，或者变换为第i-1个字符（如果有的话）或者第i+1个字符（如果有的话）。\n请计算一下最多可以变换出多少种不同的字符串，最后总数对 1000000007(109+7) 取余后输出。\n样例解释：\n样例1中，变换出来的字符串是aa, ag, ga,和 gg。\n样例2中，只能变换出aa。\n输入 多组测试数据。 第一行有一个整数T（1 ≤ T ≤ 128），表示测试数据的数目。 接下来有T组数据。 每一数据给出一个字符串S（1\u0026lt;=|S|\u0026lt;=1000，只由小写字母组成）。 输出 对于每一组数据，输出一个整数表示答案，占一行。 输入样例 样例输入1 2 ag aa 输出样例 样例输出1 4 1 解法： 统计每个位置可以变得个数，然后相乘即可 代码：\n#include\u0026lt;iostream\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;string\u0026gt; using namespace std; long long mod = 1e9 + 7; long long solve(string s) { int l = s.length(); long long ans = 1; for(int i = 0; i \u0026lt; l; i++){ set\u0026lt;char\u0026gt; c; if(i - 1 \u0026gt;= 0) c.insert(s[i - 1]); c.insert(s[i]); if(i + 1 \u0026lt; l) c.insert(s[i + 1]); ans = (ans * c.size()) % mod; } return ans; } int main() { int t; scanf(\u0026#34;%d\u0026#34;,\u0026amp;t); while(t--) { string s; cin \u0026gt;\u0026gt; s; printf(\u0026#34;%lld\\n\u0026#34;,solve(s)); } return 0; }he ","permalink":"https://eonh1u.github.io/posts/51nod-1884-%E5%8F%98%E6%8D%A2%E5%AD%97%E7%AC%A6%E4%B8%B2/","summary":"\u003cp\u003e题目:\n有一个字符串S，长度为n，现在要对其作变换。变换的规则如下：对于第i（1\u0026lt;=i\u0026lt;=n）个字符，可以保持不变，或者变换为第i-1个字符（如果有的话）或者第i+1个字符（如果有的话）。\u003c/p\u003e\n\u003cp\u003e请计算一下最多可以变换出多少种不同的字符串，最后总数对 1000000007(109+7) 取余后输出。\u003c/p\u003e","title":"51nod-1884-变换字符串"},{"content":"题目： 小b有个长度为n的数组a，她想将这个数组排序。\n然而小b很懒，她觉得对整个数组排序太累了，因此她请你将a分成一些块，使得她只需要对每一块分别排序，就能将整个数组排序。\n请问你最多能把a分成多少块。\n保证a为0\u0026hellip;n-1的一个排列。\n样例解释：\n将a分成2块或者更多块，都无法得到所需的结果。 例如，分成 [4, 3], [2, 1, 0] ，排序得到的结果是 [3, 4, 0, 1, 2]，这不是有序的数组。\n输入 第一行一个数n； 第二行n个数表示a[i]，以空格隔开。 n\u0026lt;=10 输出 输出一个数表示划分块的数量 输入样例 5 4 3 2 1 0 输出样例 1 解法：每个数字排序前排序后的下标为一段线段，相交的线段何为一段，最后求出剩下线段的个数即可。 代码：\n#include\u0026lt;set\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int a[10]; struct point { int num; int index; int sor; }; bool cmp(point a, point b) { return a.num \u0026lt; b.num; } point p[10]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++){ scanf(\u0026#34;%d\u0026#34;,\u0026amp;p[i].num); p[i].index = i; } sort(p, p + n, cmp); for(int i = 0; i \u0026lt; n; i++) p[i].sor = i; for(int i = 1; i \u0026lt; n ;i++){ for(int j = i - 1;j \u0026gt;= 0; j--){ // printf(\u0026#34;i:%d %d %d j: %d %d %d\\n\u0026#34;,i,p[i].index,p[i].sor,j,p[j].index,p[j].sor); int il = min(p[i].index, p[i].sor); int ir = max(p[i].index, p[i].sor); int jl = min(p[j].index, p[j].sor); int jr = max(p[j].index, p[j].sor); bool flag = false; if(il == jl || ir == jr) flag = true; if(il \u0026lt; jl \u0026amp;\u0026amp; ir \u0026gt; jl) flag = true; if(jl \u0026lt; il \u0026amp;\u0026amp; jr \u0026gt; il) flag = true; int Min = min(min(p[i].index,p[j].index), min(p[i].sor,p[j].sor)); int Max = max(max(p[i].index,p[j].index), max(p[i].sor,p[j].sor)); if(flag) { for(int k = 0; k \u0026lt; i; k++){ if(p[i].index == p[k].index \u0026amp;\u0026amp; p[i].sor == p[k].sor){ p[k].index = Min; p[k].sor = Max; } } p[i].index = Min; p[i].sor = Max; for(int k = 0; k \u0026lt; j; k++){ if(p[j].index == p[k].index \u0026amp;\u0026amp; p[j].sor == p[k].sor){ p[k].index = Min; p[k].sor = Max; } } p[j].index = Min; p[j].sor = Max; } } } set\u0026lt;int\u0026gt; s; // for(int i = 0; i \u0026lt; n; i++) //printf(\u0026#34;%d %d %d\\n\u0026#34;,i,p[i].index,p[i].sor); for(int i = 0; i \u0026lt; n; i++) s.insert(p[i].index); printf(\u0026#34;%d\\n\u0026#34;, s.size()); } ","permalink":"https://eonh1u.github.io/posts/51node-2502-%E5%88%86%E5%9D%97/","summary":"\u003cp\u003e题目：\n小b有个长度为n的数组a，她想将这个数组排序。\u003c/p\u003e\n\u003cp\u003e然而小b很懒，她觉得对整个数组排序太累了，因此她请你将a分成一些块，使得她只需要对每一块分别排序，就能将整个数组排序。\u003c/p\u003e\n\u003cp\u003e请问你最多能把a分成多少块。\u003c/p\u003e","title":"51node-2502-分块"},{"content":"现在有一棵n个节点的树，节点1为这棵树的根，求出每个节点的深度以及每个节点的子树中的节点个数。\n输入 第1行：一个数字n，表示树中节点的个数。(1\u0026lt;=n\u0026lt;=100000) 第2-n行：每行两个数字u,v，表示u与v之间有一条边。(1\u0026lt;=u,v\u0026lt;=n) 输出 输出n行，每行两个正整数，第i行的第一个正整数表示节点i的深度，第二个正整数表示以节点i为根的子树大小。\n解法： 水题。。。。。太水了这个 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; int p[1010]; int sum[2010]; int a[1010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); for(int i = 0; i \u0026lt; n; i++) { scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); } int ans = 0; for(int i = n - 1; i \u0026gt;= 0; i--){ if(a[i] == 0) continue; for(int j = a[i]; j \u0026lt;=2005; j++) sum[j]++; for(int j = i - 1; j \u0026gt;= 0; j--){ if(a[j] == 0) continue; int l = abs(a[i] - a[j]); int r = a[i] + a[j]; int s = sum[r - 1] - sum[l]; // printf(\u0026#34;%d %d s: %d \\n\u0026#34;,sum[r-1],sum[l],s); if(a[i] \u0026gt; l \u0026amp;\u0026amp; a[i] \u0026lt; r) s--; // printf(\u0026#34;%d %d %d\\n\u0026#34;,l,r,s); if(s \u0026gt; 0) ans += s; } } printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2627-%E6%A0%91%E7%9A%84%E6%B7%B1%E5%BA%A6%E5%A4%A7%E5%B0%8F/","summary":"\u003cp\u003e现在有一棵n个节点的树，节点1为这棵树的根，求出每个节点的深度以及每个节点的子树中的节点个数。\u003c/p\u003e\n\u003cp\u003e输入\n第1行：一个数字n，表示树中节点的个数。(1\u0026lt;=n\u0026lt;=100000)\n第2-n行：每行两个数字u,v，表示u与v之间有一条边。(1\u0026lt;=u,v\u0026lt;=n)\n输出\n输出n行，每行两个正整数，第i行的第一个正整数表示节点i的深度，第二个正整数表示以节点i为根的子树大小。\u003c/p\u003e","title":"51nod-2627-树的深度大小"},{"content":"占坑。。。明天更。。。加油！！ ps:00:53点交一发 小b有一个仅包含非负整数的数组a，她想知道有多少个三元组(i,j,k)，满足i\u0026lt;j\u0026lt;k且a[i],a[j],a[k]可能作为某个三角形的三条边的边长。\n输入 第一行输入一个正整数n，表示数组a中元素个数； 第二行n个非负整数，表示a中元素，以空格隔开； 其中0＜n≤1000，a中任意元素a[i]满足0≤a[i]≤1000。\n输出 输出一个数，表示满足题意的三元组个数 输入样例 4 2 2 3 4 输出样例 3 解法：后缀记录一下每个数出现的次数，复杂度n^2，中间因为sum数组开小了wa了一发 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; int p[1010]; int sum[2010]; int a[1010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); for(int i = 0; i \u0026lt; n; i++) { scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); } int ans = 0; for(int i = n - 1; i \u0026gt;= 0; i--){ if(a[i] == 0) continue; for(int j = a[i]; j \u0026lt;=2005; j++) sum[j]++; for(int j = i - 1; j \u0026gt;= 0; j--){ if(a[j] == 0) continue; int l = abs(a[i] - a[j]); int r = a[i] + a[j]; int s = sum[r - 1] - sum[l]; // printf(\u0026#34;%d %d s: %d \\n\u0026#34;,sum[r-1],sum[l],s); if(a[i] \u0026gt; l \u0026amp;\u0026amp; a[i] \u0026lt; r) s--; // printf(\u0026#34;%d %d %d\\n\u0026#34;,l,r,s); if(s \u0026gt; 0) ans += s; } } printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2497-%E6%95%B0%E4%B8%89%E8%A7%92%E5%BD%A2/","summary":"\u003cp\u003e占坑。。。明天更。。。加油！！\nps:00:53点交一发\n小b有一个仅包含非负整数的数组a，她想知道有多少个三元组(i,j,k)，满足i\u0026lt;j\u0026lt;k且a[i],a[j],a[k]可能作为某个三角形的三条边的边长。\u003c/p\u003e\n\u003cp\u003e输入\n第一行输入一个正整数n，表示数组a中元素个数；\n第二行n个非负整数，表示a中元素，以空格隔开；\n其中0＜n≤1000，a中任意元素a[i]满足0≤a[i]≤1000。\u003c/p\u003e","title":"51nod-2497-数三角形"},{"content":"题目: 给出区间(a,b)，b \u0026gt;= a，求𝑎 𝑥𝑜𝑟 (𝑎+1) 𝑥𝑜𝑟 (𝑎+2)\u0026hellip;..𝑥𝑜𝑟 𝑏。 输入 输入2个数：a b，中间用空格分隔(1 \u0026lt;= a \u0026lt;= b \u0026lt;= 10^9) 输出 输出一个答案 输入样例 3 8 输出样例 11\n解法： 每个相邻的奇数与偶数xor之后的值是1，所以只要记录下a到b的长度，然后根据a的奇偶进行处理就可以了 代码：\n#include\u0026lt;stdlib.h\u0026gt; #include\u0026lt;cstring\u0026gt; using namespace std; int f(int l) { l/=2; return l % 2; } int main() { int a,b; scanf(\u0026#34;%d%d\u0026#34;,\u0026amp;a,\u0026amp;b); int l = b - a + 1; //printf(\u0026#34;l %d\\n\u0026#34;, l); int ans; //printf(\u0026#34;%d\\n\u0026#34;,4) if(l \u0026amp; 1) { if(a\u0026amp;1) ans = a ^ (f(l - 1)); else ans = b ^ (f(l - 1)); } else { if(a\u0026amp;1) ans = a^b^(f(l - 2)); else ans = f(l); } printf(\u0026#34;%d\u0026#34;, ans); return 0; } ps:好久没做题，一个水题想了好久\n","permalink":"https://eonh1u.github.io/posts/51nod-2653-%E5%8C%BA%E9%97%B4xor/","summary":"\u003cp\u003e题目:\n给出区间(a,b)，b \u0026gt;= a，求𝑎 𝑥𝑜𝑟 (𝑎+1) 𝑥𝑜𝑟 (𝑎+2)\u0026hellip;..𝑥𝑜𝑟 𝑏。\n输入\n输入2个数：a b，中间用空格分隔(1 \u0026lt;= a \u0026lt;= b \u0026lt;= 10^9)\n输出\n输出一个答案\n输入样例\n3 8\n输出样例\n11\u003c/p\u003e","title":"51nod-2653-区间xor"},{"content":"题目： 给定𝑛个技能，每个技能能打掉对手𝑎𝑖的血，你一共有𝑚次发招的机会，你不能连续使用某一个技能超过𝑘次。问你最多能打掉对手多少血。\n输入 第一行3个数n,m,k，(2\u0026lt;=n\u0026lt;=2*10^5 ,1\u0026lt;=m,k\u0026lt;=10^9) 第二行n个数a[1\u0026hellip;n]，(1\u0026lt;=a[i]\u0026lt;=10^9) 输出 一个数，表示最大值。\n输入样例 6 9 2 1 3 3 7 4 2 输出样例 54 解法： 去top2，每次都是top1*k+top2,剩余的不足k就只去top1 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; int s[200010]; int main() { int n,m,k; scanf(\u0026#34;%d%d%d\u0026#34;, \u0026amp;n, \u0026amp;m, \u0026amp;k); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;s[i]); sort(s, s+n); int s1 = s[n - 1]; int s2 = s[n - 2]; long long p = s1*k + s2; long long ans = m/(k+1)*p + m%(k+1)*s1; printf(\u0026#34;%lld\\n\u0026#34;,ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2530-%E6%9C%80%E5%A4%A7%E8%BE%93%E5%87%BA/","summary":"\u003cp\u003e题目：\n给定𝑛个技能，每个技能能打掉对手𝑎𝑖的血，你一共有𝑚次发招的机会，你不能连续使用某一个技能超过𝑘次。问你最多能打掉对手多少血。\u003c/p\u003e\n\u003cp\u003e输入\n第一行3个数n,m,k，(2\u0026lt;=n\u0026lt;=2*10^5 ,1\u0026lt;=m,k\u0026lt;=10^9)\n第二行n个数a[1\u0026hellip;n]，(1\u0026lt;=a[i]\u0026lt;=10^9)\n输出\n一个数，表示最大值。\u003c/p\u003e","title":"51nod-2530-最大输出"},{"content":"题目： 给定一个0-1串，请找到一个尽可能长的子串，其中包含的0与1的个数相等。\n一个字符串，只包含01，长度不超过1000000。 输出 一行一个整数，最长的0与1的个数相等的子串的长度。 输入样例 1011 输出样例 2\n解法： 用vector记录前缀和，然后遍历求最长长度，注意处理前缀和为负数。 代码：\n#include\u0026lt;vector\u0026gt; using namespace std; char a[1000010]; vector\u0026lt;int\u0026gt; p[2000010]; int main() { scanf(\u0026#34;%s\u0026#34;,a + 1); int l = strlen(a + 1); int sum = 0; int Max = -999999999; int Min = 999999999; p[1000000].push_back(0); for(int i = 1; i \u0026lt;= l; i++) { if(a[i] == \u0026#39;0\u0026#39;) sum++; else sum--; Max = max(sum, Max); Min = min(sum, Min); p[sum + 1000000].push_back(i); } int ans = 0; //printf(\u0026#34;%d %d\\n\u0026#34;, Min, Max); for(int i = Min + 1000000; i \u0026lt;= Max + 1000000; i++) { ans = max(p[i][p[i].size() - 1]-p[i][0], ans); } printf(\u0026#34;%d\\n\u0026#34;, ans); } ps：懒惰又差点战胜了我 加油\n","permalink":"https://eonh1u.github.io/posts/1393-01%E7%9B%B8%E7%AD%89%E4%B8%B2/","summary":"\u003cp\u003e题目：\n给定一个0-1串，请找到一个尽可能长的子串，其中包含的0与1的个数相等。\u003c/p\u003e\n\u003cp\u003e一个字符串，只包含01，长度不超过1000000。\n输出\n一行一个整数，最长的0与1的个数相等的子串的长度。\n输入样例\n1011\n输出样例\n2\u003c/p\u003e","title":"1393 01相等串"},{"content":"题目： 地上有n个方块，每一个方块高度都是H，第i（1\u0026lt;=i\u0026lt;=n）个方块的长和宽分别为L[i],W[i]。\n现在开始堆方块塔，每次可以拿一个方块放到一个方块塔上，但是有一个要求，设当前塔顶的方块长度和宽度分别为Ltop,Wtop，当前拿到的方块长度和宽度分别为Lcur,Wcur，当满足Lcur\u0026lt;=Ltop\u0026amp;\u0026amp;Wcur\u0026lt;=Wtop的时候，这个方块才能被放到塔顶，并且取代之前的塔顶成为新塔顶。\n由于土地比较贵，所以想要堆出来的塔的数目尽可能少，请计算最少的塔的数目。\n例如，现在有5个方块，长度和宽度分别为：( 9 , 4 ) , ( 2 , 5 ) , ( 1 , 2 ) , ( 5 , 3 ) , ( 4 , 1 )。那么最少可以堆成两座塔：( 4 , 1 ) , ( 5 , 3 ) , ( 9 , 4 )分为一堆；( 1 , 2 ) , ( 2 , 5 )分为一堆。\n输入 单组测试数据。 第一行给出一个整数n （1 \u0026lt;= n \u0026lt;= 5000）。 第二行有2*n个整数L[1] , W[1] , L[2] , W[2] ,\u0026hellip;, L[n] , W[n]。（1\u0026lt;=L[i],W[i]\u0026lt;=10000） 输出 输出一个整数，表示答案。 输入样例 样例输入1 5 4 9 5 2 2 1 3 5 1 4 输出样例 样例输出1 解法： 按照w，l的大小进行排序，每次遍历全部，每一次遍历选出来一组符合条件的块，当所有方块被选出之后则结束，遍历的次数即为ans 代码：\n#include\u0026lt;algorithm\u0026gt; using namespace std; struct point { int x,y; }; point p[5010]; bool cmp(point a, point b) { if(a.x != b.x) return a.x \u0026lt; b.x; else { return a.y \u0026lt; b.y; } } int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); for(int i = 0; i \u0026lt; n; i++) scanf(\u0026#34;%d%d\u0026#34;,\u0026amp;p[i].x, \u0026amp;p[i].y); sort(p, p + n, cmp); //for(int i = 0; i\u0026lt; n; i++) // printf(\u0026#34;%d %d\\n\u0026#34;,p[i].x,p[i].y); int ans = 0; bool flag = false; while(!flag) { flag = true; int nx=0, ny=0; for(int i = 0; i \u0026lt; n; i++) { if(p[i].x!=0 \u0026amp;\u0026amp; p[i].y!=0) { flag = false; if(p[i].x \u0026gt;= nx \u0026amp;\u0026amp; p[i].y \u0026gt;= ny){ nx = p[i].x; ny = p[i].y; p[i].x = 0; p[i].y = 0; } } } ans++; } printf(\u0026#34;%d\\n\u0026#34;, ans - 1); return 0; } ps:最近时间都很紧迫，今天差点放弃，幸亏1A了，否则现在的我已经放弃了。加油加油！！！\n","permalink":"https://eonh1u.github.io/posts/51nod-1890-%E6%96%B9%E5%9D%97%E5%A1%94/","summary":"\u003cp\u003e\u003cstrong\u003e题目：\u003c/strong\u003e\n 地上有n个方块，每一个方块高度都是H，第i（1\u0026lt;=i\u0026lt;=n）个方块的长和宽分别为L[i],W[i]。\u003c/p\u003e\n\u003cp\u003e 现在开始堆方块塔，每次可以拿一个方块放到一个方块塔上，但是有一个要求，设当前塔顶的方块长度和宽度分别为Ltop,Wtop，当前拿到的方块长度和宽度分别为Lcur,Wcur，当满足Lcur\u0026lt;=Ltop\u0026amp;\u0026amp;Wcur\u0026lt;=Wtop的时候，这个方块才能被放到塔顶，并且取代之前的塔顶成为新塔顶。\u003c/p\u003e\n\u003cp\u003e 由于土地比较贵，所以想要堆出来的塔的数目尽可能少，请计算最少的塔的数目。\u003c/p\u003e","title":"51nod-1890-方块塔"},{"content":"给出一个数k，求最小的n，使得n的阶乘后面0的数量\u0026gt;=k。\n例如k=1，\n5的阶乘 = 12345 = 120，120后面有1个0。并且4的阶乘后面没有0，所以5是最小的结果。\n输入 一个数k(1 \u0026lt;= k \u0026lt;= 10^9) 输出 输出最小的满足条件的n。 输入样例 1 输出样例 5 解法： 每个0都是由2*5求得出来的，因而每个5之前肯定有存在足量的2，因此只需计算5的个数即可，当碰到25，50，125这种可以分解为多个5的数，便需要多计算，采用二分快速计算，二分时注意边界情况，0的个数不是连续的 代码：\nusing namespace std; int n; long long c(int x) { long long sum = x; int now = 5; while(x/now != 0) { sum += x/now; now *= 5; } return sum; } int main() { scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int l = 1, r = n; long long ans = 0; while(l \u0026lt; r) { int m = (l+ r)/2; // printf(\u0026#34;l:%d r:%d m:%d\\n\u0026#34;,l,r,m); if(c(m) \u0026lt; n) l = m + 1; else if(c(m) \u0026gt; n) r = m; else { ans = m; break; } } if(ans != 0) { printf(\u0026#34;%lld\u0026#34;, ans * 5); return 0; } if(c(l) == n) ans = l; else { ans = r; } printf(\u0026#34;%lld\u0026#34;, ans * 5); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2652-%E9%98%B6%E4%B9%980%E7%9A%84%E6%95%B0%E9%87%8F/","summary":"\u003cp\u003e给出一个数k，求最小的n，使得n的阶乘后面0的数量\u0026gt;=k。\u003c/p\u003e\n\u003cp\u003e例如k=1，\u003c/p\u003e\n\u003cp\u003e5的阶乘 = 1\u003cem\u003e2\u003c/em\u003e3\u003cem\u003e4\u003c/em\u003e5 = 120，120后面有1个0。并且4的阶乘后面没有0，所以5是最小的结果。\u003c/p\u003e","title":"51nod-2652-阶乘0的数量"},{"content":"题目: 输入一个长度为𝑛的数组𝑎，𝑎包括(𝑛−1)𝑛/2个区间。每个区间所有数的和，被称为区间和，求所有(𝑛−1)𝑛/2个区间和的和。由于数值较大，输出mod 1e9+7的结果。\n输入 第一行一个整数n，表示数组长度(2\u0026lt;=n\u0026lt;=100000) 接下来n行，每行一个整数ai，表示数组的内容。(0\u0026lt;=ai\u0026lt;=50000) 输出 输出答案mod 1e9+7 输入样例 3 1 2 3 输出样例 20 解法： 统计每个数字出现的次数就好了，每个数字出现的次数为该数字左边数字的个数乘右边的。 代码：\nusing namespace std; int main() { long long ans = 0; long long mod = 1e9+7; long long n; scanf(\u0026#34;%lld\u0026#34;,\u0026amp;n); long long e = n; for(int i = 1; i \u0026lt;=n; i++,e--) { long long a; scanf(\u0026#34;%lld\u0026#34;, \u0026amp;a); long long now = (((a*i)%mod) * e) % mod; ans = (ans + now) % mod; } printf(\u0026#34;%lld\u0026#34;, ans); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2651-%E5%8C%BA%E9%97%B4%E5%92%8C%E7%9A%84%E5%92%8C/","summary":"\u003cp\u003e题目:\n输入一个长度为𝑛的数组𝑎，𝑎包括(𝑛−1)𝑛/2个区间。每个区间所有数的和，被称为区间和，求所有(𝑛−1)𝑛/2个区间和的和。由于数值较大，输出mod 1e9+7的结果。\u003c/p\u003e\n\u003cp\u003e输入\n第一行一个整数n，表示数组长度(2\u0026lt;=n\u0026lt;=100000)\n接下来n行，每行一个整数ai，表示数组的内容。(0\u0026lt;=ai\u0026lt;=50000)\n输出\n输出答案mod 1e9+7\n输入样例\n3\n1\n2\n3\n输出样例\n20\n解法：\n统计每个数字出现的次数就好了，每个数字出现的次数为该数字左边数字的个数乘右边的。\n代码：\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-#include\u003cstdio.h\u003e\" data-lang=\"#include\u003cstdio.h\u003e\"\u003eusing namespace std;\nint main()\n{\n    long long ans = 0;\n    long long mod = 1e9+7;\n    long long  n;\n    scanf(\u0026#34;%lld\u0026#34;,\u0026amp;n);\n    long long e = n;\n    for(int i = 1; i \u0026lt;=n; i++,e--)\n    {\n        long long a;\n        scanf(\u0026#34;%lld\u0026#34;, \u0026amp;a);\n        long long now = (((a*i)%mod) * e) % mod;\n        ans = (ans + now) % mod;\n    }\n    printf(\u0026#34;%lld\u0026#34;, ans);\n    return 0;\n}\n\u003c/code\u003e\u003c/pre\u003e","title":"51nod-2651-区间和的和"},{"content":"题目： 给出一棵n个节点的树，节点编号为1-n（根节点编号为1），每一个节点作为根节点与他所有的子孙节点形成一棵子树，而这棵子树包含节点的数量，称作子树的Size。\n例如：\n1─2─4─5 └─3\n其中节点5的子树只包括节点5，Size = 1。节点4的子树包括节点4，5，Size = 2。节点1的子树包括节点1，2，3，4，5，Size = 5。\n求以所有节点为根的子树的Size之和。上面例子中，节点1到5，对应的Size分别为5，3，1，2，1，所有Size的和 = 5 + 3 + 1 + 2 + 1 = 12\n输入 第一行：1个数n（1 \u0026lt; n \u0026lt;= 1000），表示树的节点数量。 后面n-1行：每行2个数x y，表示节点x是节点y的父节点（1 \u0026lt;= x, y \u0026lt;= n）。 输出 输出1个数，表示以所有节点为根的子树的Size之和。 输入样例 5 1 2 1 3 2 4 4 5 输出样例 12\n解法: 暴力递归求解就可以，数据量再大的话可以加一下记忆化搜索。 每日划水5555555 代码:\n#include\u0026lt;queue\u0026gt; #include\u0026lt;vector\u0026gt; using namespace std; vector\u0026lt;int\u0026gt; s[10010]; bool f[10010]; int t[10010]; using namespace std; int c(int x) { int sum = 1; for(int i = 0; i \u0026lt; s[x].size(); i++) sum += c(s[x][i]); return sum; } int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int p = n - 1; while(p--) { int a,b; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;a, \u0026amp;b); f[b] = true; s[a].push_back(b); } int sum = 0; for(int i = 1; i \u0026lt;= n; i++) { sum += c(i); } printf(\u0026#34;%d\\n\u0026#34;, sum); } ","permalink":"https://eonh1u.github.io/posts/51nod-2281-%E6%A0%91%E7%9A%84size%E4%B9%8B%E5%92%8C/","summary":"\u003cp\u003e题目：\n给出一棵n个节点的树，节点编号为1-n（根节点编号为1），每一个节点作为根节点与他所有的子孙节点形成一棵子树，而这棵子树包含节点的数量，称作子树的Size。\u003c/p\u003e\n\u003cp\u003e例如：\u003c/p\u003e\n\u003cp\u003e1─2─4─5\n└─3\u003c/p\u003e\n\u003cp\u003e其中节点5的子树只包括节点5，Size = 1。节点4的子树包括节点4，5，Size = 2。节点1的子树包括节点1，2，3，4，5，Size = 5。\u003c/p\u003e\n\u003cp\u003e求以所有节点为根的子树的Size之和。上面例子中，节点1到5，对应的Size分别为5，3，1，2，1，所有Size的和 = 5 + 3 + 1 + 2 + 1 = 12\u003c/p\u003e","title":"51nod-2281-树的size之和"},{"content":"题目: n皇后。。。不多bb 直接贴代码了：\n#include\u0026lt;cmath\u0026gt; using namespace std; int f[10]; int sum = 0; int n; bool c(int x) { for(int j = 1; j \u0026lt; x; j++) { if(f[j] == f[x]) return false; if(abs(1.0*(f[j] - f[x])/(j - x)) == 1.0) return false; } return true; } void solve(int x) { for(int i = 1; i \u0026lt;= n; i++) { f[x] = i; if(c(x)) { if( x == n) sum++; else solve(x + 1); } } } int main() { scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); solve(1); printf(\u0026#34;%d\u0026#34;,sum); } 每天时间紧啊 我心里苦啊\n","permalink":"https://eonh1u.github.io/posts/51node-2067-n%E7%9A%87%E5%90%8E/","summary":"\u003cp\u003e题目:\nn皇后。。。不多bb\n直接贴代码了：\u003c/p\u003e","title":"51node-2067-n皇后"},{"content":"题目： 有𝑛个点，第𝑖号点在一维数轴的𝑖坐标位置。你现在在1号点，你需要走𝑘步，移动总长度为𝑆，问这样的方案是否存在。注意：每一步都至少移动1格，且每一步都必须从一个点移动到另一个点上。\n输入 第一行三个数n,k,s(2\u0026lt;=n\u0026lt;=10^9,1\u0026lt;=k\u0026lt;=2*10^5,1\u0026lt;=s\u0026lt;=10^18)。 输出 如果存在方案，输出YES，否则输出NO。 输入样例 10 2 15 输出样例 YES 解法： 太水了wr\u0026gt;\u0026hellip;.. 直接贴代码 代码：\n#include\u0026lt;stdio.h\u0026gt; using namespace std; int main() { long long n,k,s; scanf(\u0026#34;%lld%lld%lld\u0026#34;, \u0026amp;n, \u0026amp;k, \u0026amp;s); if(n == 1 || s \u0026lt; k) { printf(\u0026#34;NO\\n\u0026#34;); return 0; } long long sum = k*(n-1); if(sum \u0026gt;= s) printf(\u0026#34;YES\\n\u0026#34;); else printf(\u0026#34;NO\\n\u0026#34;); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-2529-%E7%A7%BB%E5%8A%A8/","summary":"\u003cp\u003e题目：\n 有𝑛个点，第𝑖号点在一维数轴的𝑖坐标位置。你现在在1号点，你需要走𝑘步，移动总长度为𝑆，问这样的方案是否存在。注意：每一步都至少移动1格，且每一步都必须从一个点移动到另一个点上。\u003c/p\u003e","title":"51nod-2529-移动"},{"content":"题目： 给出一棵n个节点的树，节点编号为1-n（根节点编号为1），求这棵树叶子结点的数量。 例如：\n1─2─4─5 └─3\n其中3和5是叶子节点，输出2。\n输入 第一行：1个数n（1 \u0026lt; n \u0026lt;= 1000），表示树的节点数量。 后面n-1行：每行2个数x y，表示节点x是节点y的父节点（1 \u0026lt;= x, y \u0026lt;= n）。 输出 输出1个数，表示这棵树有多少个叶子节点。 输入样例 5 1 2 1 3 2 4 4 5 输出样例 2 解法： 记录是否有子节点即可，最后没有子节点的即为叶子节点 ps(加班没时间，，，写了个水题，签到） 代码：\nusing namespace std; int a[1010]; int main() { int n; scanf(\u0026#34;%d\u0026#34;, \u0026amp;n); int p = n -1 ; int ans = 0; while(p--) { int s,e; scanf(\u0026#34;%d%d\u0026#34;, \u0026amp;s, \u0026amp;e); a[s]++; } for(int i = 1; i \u0026lt;= n; i++) if(a[i] == 0) ans++; printf(\u0026#34;%d\\n\u0026#34;, ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-2423-%E5%8F%B6%E5%AD%90%E8%8A%82%E7%82%B9%E7%9A%84%E6%95%B0%E9%87%8F/","summary":"\u003cp\u003e题目：\n给出一棵n个节点的树，节点编号为1-n（根节点编号为1），求这棵树叶子结点的数量。\n例如：\u003c/p\u003e\n\u003cp\u003e1─2─4─5\n└─3\u003c/p\u003e\n\u003cp\u003e其中3和5是叶子节点，输出2。\u003c/p\u003e","title":"51nod-2423-叶子节点的数量"},{"content":"题目: 工厂里面，有n根待加工的铁棒，长度以米为单位，精确到小数点后两位（即厘米），现在市场上需求量是m根相同长度的铁棒。现在厂长想把这n根铁棒进行切割，切割的时候要精确到厘米，比如说，原来铁棒是1.00米的，那么可以切成0.50和0.50的，但是不能切成0.499和0.501的。并且不能将两根铁棒拼成一根铁棒。现在厂长想知道切出来的m根铁棒最长能有多长。\n输入 单组测试数据。 第一行给出两个整数n(1 \u0026lt;= n\u0026lt;= 10000)和m(1 \u0026lt;= m\u0026lt; = 10000)。 接下来n行给出原始铁棒的长度L[1],L[2],L[3],\u0026hellip;,L[n] ，(1\u0026lt;=L[i]\u0026lt;=100,000)。以米为单位，精确到小数点后两位。 输出 输出一个小数表示答案，精确到小数点后两位。 输入样例 样例输入1 4 11 8.02 7.43 4.57 5.39 输出样例 样例输出1 2.00 解法： 二分分情况讨论即可，因为题目有小数点限制，这里我直接*100 最后/100处理了这个情况 ps:(每天没时间刷题555555，选个一眼题找找手感，二分的边界情况还是有点乱，改天整理一下） 代码\nusing namespace std; int n,m; int a[100010]; bool c(int x) { if(x == 0) return true; long long sum = 0; for(int i = 0; i \u0026lt; n; i++) sum += a[i]/x; return sum \u0026gt;= m; } int main() { scanf(\u0026#34;%d%d\u0026#34;,\u0026amp;n,\u0026amp;m); for(int i = 0; i \u0026lt; n; i++){ double s; scanf(\u0026#34;%lf\u0026#34;, \u0026amp;s); a[i] = s*100; } int l = 1, r = 10000000; for(int i = 0; i \u0026lt; 200; i++) { int m = (l+r)/2; if(c(m)) l = m; else r = m - 1; } if(c(r)) printf(\u0026#34;%.2f\\n\u0026#34;,r*1.0/100); else printf(\u0026#34;%.2f\\n\u0026#34;,l*1.0/100); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1889-%E5%88%B6%E9%93%81%E6%A3%92/","summary":"\u003cp\u003e\u003cstrong\u003e题目:\u003c/strong\u003e\n 工厂里面，有n根待加工的铁棒，长度以米为单位，精确到小数点后两位（即厘米），现在市场上需求量是m根相同长度的铁棒。现在厂长想把这n根铁棒进行切割，切割的时候要精确到厘米，比如说，原来铁棒是1.00米的，那么可以切成0.50和0.50的，但是不能切成0.499和0.501的。并且不能将两根铁棒拼成一根铁棒。现在厂长想知道切出来的m根铁棒最长能有多长。\u003c/p\u003e","title":"51nod-1889-制铁棒"},{"content":"题目： 有一个无限大的蜂巢迷宫，为了方便表示每一个六边形格子，现在把座标引入到这个迷宫中，如上图年示。\n艾瑞特在这个迷宫中街，刚开始他在(0,0)的位置，按照下图所示的路线在这个迷宫中行走。 图片贴不上 这里附上原题目的链接： http://www.51nod.com/Challenge/Problem.html#problemId=1740\n题解： 找规律即可（好久没刷题 太菜了 debug找了好久） 代码：\n#include\u0026lt;cmath\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int main() { long long n; scanf(\u0026#34;%lld\u0026#34;, \u0026amp;n); if(n == 0) { printf(\u0026#34;0 0\u0026#34;); return 0; } // for(int i = 1; i \u0026lt; 20; i++){ // n = i; n++; long long len = 1; long long sum = len; while(sum \u0026lt; n) { sum += len*6; len++; } long long now = n -1 - (len - 1)*(len-2)*3; //printf(\u0026#34;now %d\\n\u0026#34;,now); long long Time = now / (len - 1); now %= len - 1; long long x ,y; // printf(\u0026#34;%d %d\\n\u0026#34;,Time, len); if(Time == 0) { x = 2 * (len - 1); y = 0; while(now--) x--,y+=2; } else if(Time == 1) { x = len - 1; y = 2*(len - 1); while(now--) x-=2; } else if(Time == 2) { x = 1 - len; y = 2*(len - 1); while(now--) x--,y-=2; } else if(Time == 3) { x = 2*(1-len); y = 0; while(now--) x++,y-=2; } else if(Time == 4) { x = 1-len; y = 2*(1 - len); while(now--) x+=2; } else if(Time == 5) { x = len - 1; y = 2*(1 - len); while(now--) x++,y+=2; } else { x = 2*(len - 1); y = 0; } printf(\u0026#34;%lld %lld\\n\u0026#34;,x,y); // } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1740-%E8%9C%82%E5%B7%A2%E8%BF%B7%E5%AE%AB/","summary":"\u003cp\u003e题目：\n有一个无限大的蜂巢迷宫，为了方便表示每一个六边形格子，现在把座标引入到这个迷宫中，如上图年示。\u003c/p\u003e\n\u003cp\u003e艾瑞特在这个迷宫中街，刚开始他在(0,0)的位置，按照下图所示的路线在这个迷宫中行走。\n图片贴不上 这里附上原题目的链接：\n\u003ca href=\"http://www.51nod.com/Challenge/Problem.html#problemId=1740\"\u003ehttp://www.51nod.com/Challenge/Problem.html#problemId=1740\u003c/a\u003e\u003c/p\u003e","title":"51nod-1740 蜂巢迷宫"},{"content":"今天周六，偷个懒选了个非常easy 的题目 题目： 有一个字符串S，下标从1开始，初始为S=\u0026ldquo;0\u0026rdquo;。现在开始调用fun函数。\n{ for(i=0;i\u0026lt;100000;i++) { tmp=change(S); S=S+\u0026#34;0\u0026#34;+tmp; } } change(s) { for(i=1;i\u0026lt;=s.length();i++) { if(s[i]==\u0026#39;0\u0026#39;)s[i]=\u0026#39;1\u0026#39;; else s[i]=\u0026#39;0\u0026#39;; } i=1; j=s.length(); while(i\u0026lt;=j) { tmp=s[i]; s[i]=s[j]; s[j]=tmp; i++; j--; } return s; } 现在有若干个查询，每一个查询有一个整数n，我们想知道字符串S第n位是什么。 解法： 通过找规律可以找到串是在每个2^n的地方都反对称的，所以进行递归进行处理即 可，2^n的位置即为0 代码:\n#include\u0026lt;cmath\u0026gt; #include\u0026lt;algorithm\u0026gt; using namespace std; int solve(long long a, int flag) { if(a \u0026lt;= 3) { if(a == 3) return abs(1 - flag); else return abs(0 - flag); } else { //printf(\u0026#34;a %lld\\n\u0026#34;, a); int i = 0; long long p = a; while(p != 1){ p /= 2; i++; } long long now = 1; while(i--) now *= 2; if(now == a) return abs(0-flag); flag = abs(1 - flag); return solve(2 * now - a,flag); } } int main() { int t; scanf(\u0026#34;%d\u0026#34;, \u0026amp;t); while(t--) { long long a; scanf(\u0026#34;%lld\u0026#34;, \u0026amp;a); printf(\u0026#34;%d\\n\u0026#34;, solve(a,0)); } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1886-%E5%8F%A0%E5%8A%A0%E4%B8%B2/","summary":"\u003cp\u003e今天周六，偷个懒选了个非常easy 的题目\n题目：\n有一个字符串S，下标从1开始，初始为S=\u0026ldquo;0\u0026rdquo;。现在开始调用fun函数。\u003c/p\u003e","title":"51nod-1886-叠加串"},{"content":"题目： 又到了一年毕业季，Noder也从学校毕业了。现在Noder要把东西进行打包，打包完成后，Noder的所有东西都被装进了若干个长方体形状的收纳盒中，这些收纳盒的高都是1024，底座是正方形且边长都是1到6之间的整数。现在Noder要进行搬家了，他有一辆车，这个车子的后备箱是一个长方体，高为1024，底座为边长是6的正方形，那么Noder想知道，他最少要运几趟才能把他所有的东西运完呢？\n解法： 题目还是比较容易理解的，矩形里面套矩形，怎么使得次数最少，分情况讨论即可（代码也太不简洁了）直接贴代码了😂😂 代码:\n#include\u0026lt;stdio.h\u0026gt; #include\u0026lt;iostream\u0026gt; using namespace std; int a[7]; int main() { for(int i = 1; i \u0026lt; 7; i++) scanf(\u0026#34;%d\u0026#34;, \u0026amp;a[i]); int ans = 0; ans += (a[4] + a[5] + a[6]); a[1] -= a[5] * 11; a[5] = 0; if(a[1] \u0026lt; 0) a[1] = 0; int p = a[2]/5; if(p \u0026gt;= a[4]) { a[2] -= a[4]*5; a[4] = 0; } else { a[2] -= p*5; a[4] -= p; } if(a[4] \u0026gt; 0) { if(a[1] \u0026gt; 0) { a[1] -= 20-a[2]*4; a[2] = 0; a[4]--; a[1] -= a[4]*20; } else a[2]=0; if(a[1] \u0026lt; 0) a[1] = 0; } //cout \u0026lt;\u0026lt;ans \u0026lt;\u0026lt;endl; //for(int i = 1; i \u0026lt; 7; i++) // printf(\u0026#34;%d %d\\n\u0026#34;,i, a[i]); ans += a[3] / 4; a[3] = a[3] % 4; ans += a[2] / 9; a[2] = a[2] % 9; //cout \u0026lt;\u0026lt;ans \u0026lt;\u0026lt;endl; // for(int i = 1; i \u0026lt; 7; i++) // printf(\u0026#34;%d %d\\n\u0026#34;,i, a[i]); // cout \u0026lt;\u0026lt; ans \u0026lt;\u0026lt;endl; if(a[3] == 0) { int sum = a[2] * 4 + a[1]; if(sum % 36 !=0) ans += sum/36 + 1; else ans += sum/36; } else if(a[3] == 1) { if(a[2] \u0026gt;= 5) { a[2] -= 5; a[1] -= 7; if(a[1] \u0026lt; 0) a[1] = 0; ans++; int sum = a[2] * 4 + a[1]; if(sum % 36 !=0) ans += sum/36 + 1; else ans += sum/36; } else { int sum = 27 - a[2] * 4; a[1] -= sum; if(a[1]\u0026lt;0) a[1] = 0; ans++; if(a[1] % 36 != 0) ans += a[1]/36 +1; else ans += a[1]/36; } } else if(a[3] == 2) { if(a[2] \u0026gt;= 3) { a[2] -=3; a[1] -= 6; if(a[1] \u0026lt; 0) a[1] = 0; ans++; int sum = a[2] * 4 + a[1]; if(sum % 36 !=0) ans += sum/36 + 1; else ans += sum/36; } else { int sum = 18 - a[2] * 4; a[1] -= sum; if(a[1]\u0026lt;0) a[1] = 0; ans++; if(a[1] % 36 != 0) ans += a[1]/36 +1; else ans += a[1]/36; } } else if(a[3] == 3) { if(a[2] \u0026gt;= 1) { a[2] -= 1; a[1] -= 5; if(a[1] \u0026lt; 0) a[1] = 0; ans++; int sum = a[2] * 4 + a[1]; if(sum % 36 !=0) ans += sum/36 + 1; else ans += sum/36; } else{ int sum = 9; a[1] -= sum; if(a[1]\u0026lt;0) a[1] = 0; ans++; if(a[1] % 36 != 0) ans += a[1]/36 +1; else ans += a[1]/36; } } printf(\u0026#34;%d\\n\u0026#34;,ans); } ","permalink":"https://eonh1u.github.io/posts/51nod-1877-%E6%89%93%E5%8C%85/","summary":"\u003cp\u003e题目：\n又到了一年毕业季，Noder也从学校毕业了。现在Noder要把东西进行打包，打包完成后，Noder的所有东西都被装进了若干个长方体形状的收纳盒中，这些收纳盒的高都是1024，底座是正方形且边长都是1到6之间的整数。现在Noder要进行搬家了，他有一辆车，这个车子的后备箱是一个长方体，高为1024，底座为边长是6的正方形，那么Noder想知道，他最少要运几趟才能把他所有的东西运完呢？\u003c/p\u003e","title":"51nod 1877 打包"},{"content":"题目： 奥林匹克竞赛从1989年开始举行，每一个奥林匹克年都会有一个缩写IAO\u0026rsquo;y， y表示那一年的最后几位数字。 组织者会取一个之前未被用过的缩写来表示该年份，而且要尽可能的短。\n例如，前三个奥林匹克年是1989，1990和1991，他们对应的缩写是IAO'9， IAO'0 和IAO'1，而2015的缩写是IAO'15，因为IAO'5已经被1995用过了。\n现在给出一个缩写，请判断这个是代表哪一年的。\n多组测试数据。 输入 第一行有一个整数n (1≤n≤1000) ，表示要处理n组数据。 接下来n行，每一行有一个缩写。每一个缩写最多包含9位数字。 输出 对于每一个缩写，请输出对应的年份。 样例 5 IAO'15 IAO'2015 IAO'1 IAO'9 IAO'0\n2015 12015 1991 1989 1990 做法： 经过思考并且打表找规律后。可以先预处理将位数比较小的数进行存储，用map映射即可，对于位数比较大的，全部预处理肯定不现实，规律如下：对于输入的每个数，数字的变化发生在1(*)3099处，举个例子，如果输入的是六位数，则113098之前的（包括113098），则ans为1113098，即之间在前面补1，如果大于等于113099，则直接输出，不用做任何处理。 代码\n#include\u0026lt;algorithm\u0026gt; #include\u0026lt;string\u0026gt; #include\u0026lt;cstring\u0026gt; #include\u0026lt;set\u0026gt; #include\u0026lt;map\u0026gt; #include\u0026lt;iostream\u0026gt; using namespace std; map\u0026lt;string, int\u0026gt; m; set\u0026lt;string\u0026gt; s; int main() { for(int i = 1989; i \u0026lt;= 100000; i++) { int p = i; string str = \u0026#34;\u0026#34;; string now = str + char(int(\u0026#39;0\u0026#39;)+ p%10); while(s.find(now) != s.end()) { p/=10; str = now; now = char(int(\u0026#39;0\u0026#39;)+ p%10) + str; } //cout\u0026lt;\u0026lt;now\u0026lt;\u0026lt;\u0026#34; \u0026#34;; s.insert(now); m[now] = i; //printf(\u0026#34;%d\\n\u0026#34;,i); } int t; scanf(\u0026#34;%d\u0026#34;,\u0026amp;t); char c; scanf(\u0026#34;%c\u0026#34;,\u0026amp;c); //cout \u0026lt;\u0026lt; t \u0026lt;\u0026lt;endl; while(t--) { char a[10]; scanf(\u0026#34;IAO\\\u0026#39;%s%c\u0026#34;,a,\u0026amp;c); //cout \u0026lt;\u0026lt; a \u0026lt;\u0026lt;endl; if(strlen(a) \u0026lt;= 4) printf(\u0026#34;%d\\n\u0026#34;, m[a]); else { int l = strlen(a); int rsum = (a[l-1] - \u0026#39;0\u0026#39;) + 10*(a[l-2]-\u0026#39;0\u0026#39;) + 100*(a[l-3]-\u0026#39;0\u0026#39;) + 1000*(a[l-4]-\u0026#39;0\u0026#39;); int now = 1; int p = l - 5; while(p--) { now = now * 10 + 1; } int lsum = 0; //cout \u0026lt;\u0026lt; \u0026#34;p \u0026#34;\u0026lt;\u0026lt;p\u0026lt;\u0026lt;endl; for(int i = 0; i \u0026lt; l - 4; i++) lsum = lsum * 10 + (a[i] - \u0026#39;0\u0026#39;); // cout \u0026lt;\u0026lt; \u0026#34;lsum rsum\u0026#34;\u0026lt;\u0026lt;lsum\u0026lt;\u0026lt;\u0026#34; \u0026#34;\u0026lt;\u0026lt;rsum\u0026lt;\u0026lt;endl; if(lsum \u0026lt; now) printf(\u0026#34;1%s\\n\u0026#34;,a); else if(lsum == now \u0026amp;\u0026amp; rsum \u0026lt; 3099) printf(\u0026#34;1%s\\n\u0026#34;,a); else printf(\u0026#34;%s\\n\u0026#34;,a); } } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-%E5%A5%A5%E6%9E%97%E5%8C%B9%E5%85%8B%E5%B9%B4/","summary":"\u003cp\u003e\u003cstrong\u003e题目：\u003c/strong\u003e\n奥林匹克竞赛从1989年开始举行，每一个奥林匹克年都会有一个缩写IAO\u0026rsquo;y， y表示那一年的最后几位数字。 组织者会取一个之前未被用过的缩写来表示该年份，而且要尽可能的短。\u003c/p\u003e\n\u003cp\u003e例如，前三个奥林匹克年是1989，1990和1991，他们对应的缩写是IAO'9， IAO'0 和IAO'1，而2015的缩写是IAO'15，因为IAO'5已经被1995用过了。\u003c/p\u003e\n\u003cp\u003e现在给出一个缩写，请判断这个是代表哪一年的。\u003c/p\u003e","title":"51nod 奥林匹克年"},{"content":"题目： 统计一下 𝑎𝑎𝑎 ⋯ 𝑎𝑎𝑎（𝑛个𝑎） × 𝑏 的结果里面有多少个数字d，a,b,d均为一位数。\n样例解释：\n3333333333*3=9999999999，里面有10个9。\n解法： 打表可以得到，相乘的结果最多有4个不同的数字，如果n比较小暴力即可，如果n比较大的话，先求出这4个数字（可能有相同），然后根据n的大小得出。 结果的表示方法sl*re l可能有多位。\n#include \u0026lt;algorithm\u0026gt; using namespace std; int main() { int t = 0; scanf(\u0026#34;%d\u0026#34;,\u0026amp;t); while(t--) { int a,b,d,n; scanf(\u0026#34;%d%d%d%d\u0026#34;, \u0026amp;a, \u0026amp;b, \u0026amp;d, \u0026amp;n); if(n \u0026lt; 5){ int now = 1; n--; while(n--) { now = now * 10 + 1; } int sum = a*now * b; int ans = 0; while(sum) { if(sum % 10 == d) ans++; sum /= 10; } printf(\u0026#34;%d\\n\u0026#34;,ans); } else{ int num = a*11111*b; int now = a * b; int len; if(now \u0026gt;= 10) len = 1; else len = 0; //printf(\u0026#34;%d\\n\u0026#34;,num); int s,l,r,e; e = num % 10; num /= 10; r = num %10; num /= 10; l = num % 10; num /= 10; while(num \u0026gt; 10) num /= 10; s = num; int sum = 0; if(d == s) sum++; if(d == r) sum++; if(d == l) sum += n-3+len; if(d == e) sum++; printf(\u0026#34;%d\\n\u0026#34;,sum); } } return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1770-%E6%95%B0%E6%95%B0%E5%AD%97/","summary":"\u003cp\u003e\u003cstrong\u003e题目：\u003c/strong\u003e\n统计一下 𝑎𝑎𝑎 ⋯ 𝑎𝑎𝑎（𝑛个𝑎） × 𝑏 的结果里面有多少个数字d，a,b,d均为一位数。\u003c/p\u003e\n\u003cp\u003e样例解释：\u003c/p\u003e\n\u003cp\u003e3333333333*3=9999999999，里面有10个9。\u003c/p\u003e","title":"51nod-1770"},{"content":"题目： 羊村的羊们为了过冬，他们要在夏天的时候存储一些食物。等到冬天时拿出来吃。他们把食物包装成1×1×1的小方块，以便存储和取出来食用。经过了一个夏天后，小羊们存储了A·B·C块食物。他们把食物放到一个长方体的小屋里，A层高，每层有B行，每行有C块食物。\n在秋天过后，村长来到小屋，要打开门分发食物了。但是，很不幸，小屋的四周都散落着食物块。经过查证，小偷们从小屋的顶层，前面，后面，和侧面都偷走了一个面的食物，一个面的食物指的是紧贴着某个面食物。所以剩下只有 （𝐴−1）×（𝐵−2）×（𝐶−2） 块食物。为了隐藏罪证，小偷们把剩下的食物块，全部打乱，散落在小屋的四周。所以村长忘记了原来A，B，C到底是多少。\n现在给定n，表示剩下的食物数量。计算可能最小和最大被偷走的食物数量。\n样例解释：\n在样例中，如果原来的数量为32＝2×4×4，现在的数量是4＝（2-1）×（4-2）×（4-2），则被偷走的是32-4＝28块。 如果原来的数量为45＝5×3×3，现在的数量是4＝（5-1）×（3-2）×（3-2），则被偷走的是45-4＝41块。\n解法： 暴力遍历所有方法即可\nps：初始想法错误，初始想法是想找方差最小的ABC，即为MIN；1，1，n即为MAX；并且abc中与1相乘的越大，最终得到的结果越小，此想法为错误的。最终选择了暴力的做法。复杂度为n的2/3次方\n#include \u0026lt;cmath\u0026gt; #include \u0026lt;algorithm\u0026gt; using namespace std; int main() { int n; long long a[3]; long long Min = 9999999999999999, Max = 0; scanf(\u0026#34;%d\u0026#34;,\u0026amp;n); long long x = pow(n, 1.0/3); for(int i = 1; i \u0026lt;= x; i++) { int p = n; if(p % i == 0) { p /= i; a[0] = i; int k = sqrt(p); for(int j = 1; j \u0026lt;= k; j++){ if(p % j == 0) { a[1] = j; a[2] = p/a[1]; //printf(\u0026#34;%lld %lld %lld\\n\u0026#34;, a[0], a[1], a[2]); Min = min(Min,(a[0]+1)*(a[1]+2)*(a[2]+2)); Min = min(Min,(a[1]+1)*(a[0]+2)*(a[2]+2)); Min = min(Min,(a[2]+1)*(a[1]+2)*(a[0]+2)); Max = max(Max,(a[0]+1)*(a[1]+2)*(a[2]+2)); Max = max(Max,(a[1]+1)*(a[0]+2)*(a[2]+2)); Max = max(Max,(a[2]+1)*(a[1]+2)*(a[0]+2)); } } } } printf(\u0026#34;%lld %lld\\n\u0026#34;, Min - n, Max - n); return 0; } ","permalink":"https://eonh1u.github.io/posts/51nod-1744-codeforce-143c/","summary":"\u003cp\u003e\u003cstrong\u003e题目：\u003c/strong\u003e\n羊村的羊们为了过冬，他们要在夏天的时候存储一些食物。等到冬天时拿出来吃。他们把食物包装成1×1×1的小方块，以便存储和取出来食用。经过了一个夏天后，小羊们存储了A·B·C块食物。他们把食物放到一个长方体的小屋里，A层高，每层有B行，每行有C块食物。\u003c/p\u003e\n\u003cp\u003e在秋天过后，村长来到小屋，要打开门分发食物了。但是，很不幸，小屋的四周都散落着食物块。经过查证，小偷们从小屋的顶层，前面，后面，和侧面都偷走了一个面的食物，一个面的食物指的是紧贴着某个面食物。所以剩下只有 （𝐴−1）×（𝐵−2）×（𝐶−2） 块食物。为了隐藏罪证，小偷们把剩下的食物块，全部打乱，散落在小屋的四周。所以村长忘记了原来A，B，C到底是多少。\u003c/p\u003e","title":"51nod-1744 codeforce-143c"},{"content":"此文将第一次对k8s的感受以及对k8s中的部分的作用进行解释，在解释的过程中不采用特别拗口专业的词汇，试着将其中的部件用实例的方式描述清楚。当然这只是简单的将自己的现在的理解（2018，12，28）用文字表述出来，肯定是有很多错误的，并且对其中各个部件具体的组成不会介绍。已经将会随着学习的深入，将描述变得清晰一点。\n1.Master与Node Master与Node在现实中对的你可以理解为一台电脑，一个虚拟机，一台服务器这种例子，我们在进行配置的时候可以根据地址指定某台为Master或者Node。Master与Node可以共存，也就是说可以指定某台为Master的同时并将其当作Node。 Master的作用是：对整个集群进行调度，并提供系统进行操作的接口 Node的作用是：同劳动力一样，就是进行劳动，将Master所分配的任务完成就好。\n2.Docker与Pod Docker是一个容器，可以理解为Docker是我们需要运行某个程序所需要的环境以及资源，Docker是完全沙箱隔离的（陪环境什么的去死吧），比如我们向写一个简单的c语言的hello-world程序，我们便可以在一个docker中进行编写，同时在运行docker的系统中不需要配置任何环境，我们只需要创建一个包含此hello-world的镜像的docker进行运行，便可以，然后运行结束之后，系统与原来的一样，不含任何杂质。 Pod是k8s进行操作的最小单位，意思是k8s进行调度时，便是对pod的分配进行调度。 在一个Pod中可以含有多个Pod，Pod的结构可以由用户自己编写，可以简单的理解为Pod时需要运行的程序，在Pod中的多个Docker便是程序的的组成。在一个Pod中的多个Docker共享Pod中的资源，并且多个Docker之间可以进行localhost访问。\n3.Service 可以这么简单的理解，现在我们定义了一个可以计算a+b的Pod，并且将Pod运行在了多个Node中（一个Node中对应一个a+b的Pod），其中每个node中的Pod程序都是完全相同的，这就是副本。但是程序相同的Pod具有不同的ip，为了方便执行程序，我们用Service将Pod进行绑定，当我们指明要执行a+b这个Service时，k8s将会自动的找到相应的Node去调用Pod来执行。\n4.label 可以将label理解为简单的表格，通过此表格我们可以根据不同的值，找到相对应的Pod，Node等结构，同时在label中也记录了结构之间的关系，例如，Pod与Node的对应关系。\n5.Replication Controller 目前的了解还不是很清楚，可以大概的认为，RC是一个请求执行程序的要求，在其中包含了Pod的组成即任务的要求，还有Pod需要运行的副本的数量等信息。\n下面将k8s一次执行的流程进行简单的描述： 1.我们通过kubectl命令通过API Server提交一个创建RC的的请求，在请求的过程中，该请求记录被记录在etcd中 2.提交请求的过程中，Controller Manager通过API Server得到了此请求的信息，发现现在并没有此RC的Pod实例，于是便根据RC中的Pod描述，创建一个Pod对象，并且也将此过程通过API Server记录在etcd中。 3.在Controller Manager创建对象完成后，Scheduler便通过一系列计算选择一个Node节点，并将此Pod放置在此Node中，并且也将此结果通过API Server记录在etcd中。 4.调度结果出来后，被选择的Node节点从API Server中得到自己被选中的信息，便按照Pod的定义，在本地进行执行，并且一直负责，直到该Pod的结束。\n从这个简单流程中，我们可以知道，API Server为所有部件的连接桥，负责信息的交流，同时在过程中产生的信息以及关系都会通过API Server记录在etcd中。\n","permalink":"https://eonh1u.github.io/posts/k8s%E5%88%9D%E4%BD%93%E9%AA%8C/","summary":"\u003cp\u003e此文将第一次对k8s的感受以及对k8s中的部分的作用进行解释，在解释的过程中不采用特别拗口专业的词汇，试着将其中的部件用实例的方式描述清楚。当然这只是简单的将自己的现在的理解（2018，12，28）用文字表述出来，肯定是有很多错误的，并且对其中各个部件具体的组成不会介绍。已经将会随着学习的深入，将描述变得清晰一点。\u003c/p\u003e\n\u003ch3 id=\"1master与node\"\u003e1.Master与Node\u003c/h3\u003e\n\u003cp\u003eMaster与Node在现实中对的你可以理解为一台电脑，一个虚拟机，一台服务器这种例子，我们在进行配置的时候可以根据地址指定某台为Master或者Node。Master与Node可以共存，也就是说可以指定某台为Master的同时并将其当作Node。\nMaster的作用是：对整个集群进行调度，并提供系统进行操作的接口\nNode的作用是：同劳动力一样，就是进行劳动，将Master所分配的任务完成就好。\u003c/p\u003e","title":"k8s初体验"},{"content":" 约瑟夫环问题：有n个人围成一个圈，标号分别为0～n-1，从第一个人开始从1进行数数，数到k的人淘汰出圈外，求最后一个被淘汰的人的编号。 之前比较暴力的解法就是用线性结构模拟环，模拟淘汰的过程，复杂度为O(NK) 利用递推的思想我们可以实现O(N)的复杂度。 推理的思路如下：\n我们第一次淘汰的人的下标很容易得出，即 x1=(k-1)%n (这个式子我们可以通通过几个简单的例子得到，例如n=4,k=5;n=4,k=5;n=3,k=1;这三个例子可以验证我们得到的式子的正确性） 那我们得到了x1，怎么计算第二次的？假设我们第一次时，k\u0026lt;n 则数列初始状态为0,1,2,3,4,\u0026hellip;n-1，第一次淘汰掉k-1，则剩下0,1,2,3..k-2,k,..n-1;，我们将剩下的人重新排序，以第一次淘汰结束后的k为0，则状态变为n-k,n-k+1,n-k+2,n-k+3..n-2,0,..n-1..n-k-1; 人的标号范围变为0～n-2 那我们在第二次的标号规则下，淘汰的人的标号为 x2=(x1+k-1)%(n-1) 我们知道最后一次淘汰的，在最后一次的标号规则下，编号即为0 我们记f(i)为第i次淘汰的人在第i次淘汰时的编号，则f(0)=0 我们所需要做的是，通过f(i-1)推出f(i)，通过上面的对照表，我们可以得到 f(i)=(f(i-1)+k)%n 应该也是可以从 x2=(x1+k-1)%(n-1) 此公式得出，但目前。。。我还不会推。 所以我们可以通过递推最终得到f(n)，即最后一次被淘汰的人的编号。\n","permalink":"https://eonh1u.github.io/posts/%E7%BA%A6%E7%91%9F%E5%A4%AB%E7%8E%AF-%E9%80%92%E6%8E%A8/","summary":"\u003cp\u003e       约瑟夫环问题：有n个人围成一个圈，标号分别为0～n-1，从第一个人开始从1进行数数，数到k的人淘汰出圈外，求最后一个被淘汰的人的编号。\n       之前比较暴力的解法就是用线性结构模拟环，模拟淘汰的过程，复杂度为O(NK)\n       利用递推的思想我们可以实现O(N)的复杂度。\n       推理的思路如下：\u003c/p\u003e","title":"约瑟夫环-递推"},{"content":"A题题意：有一长度为N的连续序列，A与B交替从序列中取一段连续序列，每次取的序列长度为1-K，当某个人进行选择时，序列为空，则另一人获得胜利，A先进行选择，输入获胜者。 样例：\nInput Output 1 1 A 9 3 A 第一遍读题出现了错误，理解为序列会进行合并，采取了不理智的做法，直接吃了一发WA 第二遍读懂题目，发现是个基础的博弈，因为是A先选取，所以只要A在选取的时候，使得剩下的段为对称的，那每次B选取一段，A便选取相之对称的段，则A必获得胜利。所以我们考虑，当K\u0026gt;=2时，我们不管N为多大，我们都可使得A获得胜利（当N\u0026lt;=2,A直接取完，当N\u0026gt;2时，若N为奇数，我们在序列中间取1，使得剩下的段为对称的，若N为偶数，在中间取2使得段落变为对称），当k为1时，我们只需判断N的奇偶性便可确定谁最终胜利。 代码如下：\nusing namespace std; int main() { int n,k; while(~scanf(\u0026#34;%d%d\u0026#34;,\u0026amp;n,\u0026amp;k)) { if(k\u0026gt;=2) printf(\u0026#34;Adrien\\n\u0026#34;); else if(n\u0026amp;1) printf(\u0026#34;Adrien\\n\u0026#34;); else printf(\u0026#34;Austin\\n\u0026#34;); } return 0; } ","permalink":"https://eonh1u.github.io/posts/2018icpc%E5%8D%97%E4%BA%ACa%E9%A2%98/","summary":"\u003cp\u003eA题题意：有一长度为N的连续序列，A与B交替从序列中取一段连续序列，每次取的序列长度为1-K，当某个人进行选择时，序列为空，则另一人获得胜利，A先进行选择，输入获胜者。\n\u003cstrong\u003e样例：\u003c/strong\u003e\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eInput\u003c/th\u003e\n          \u003cth\u003eOutput\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e1 1\u003c/td\u003e\n          \u003ctd\u003eA\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e9 3\u003c/td\u003e\n          \u003ctd\u003eA\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e","title":"2018icpc南京A题"},{"content":"新的路开始了\n","permalink":"https://eonh1u.github.io/posts/woo/","summary":"\u003cp\u003e\u003cem\u003e新的路开始了\u003c/em\u003e\u003c/p\u003e","title":"Start"}]