Codeforces Round #613 (Div. 2)D(贪心,分治)

构造两颗深度为30的字典树(根节点分别是0和1),结点只有0和1,从根节点向下DFS,贪心取答案。

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 vector<int>a;
 5 int dfs(vector<int>b,int x){
 6     if(x<0||b.size()==0)//30位都枚举完毕或当前向量中没有数字就中止
 7         return 0;
 8     vector<int>c,d;
 9     for(int i=0;i<b.size();++i){
10         if((b[i]>>x)&1)
11             c.push_back(b[i]);//当前位为1的数放进c
12         else
13             d.push_back(b[i]);//当前位为0的数放进d
14     }
15     if(c.size()==0)//b中所有数字当前位都为1,那么可以把题意中X的当前位构造为1(假定这一位是1),异或下来这一位就是0
16         return dfs(d,x-1);
17     else if(d.size()==0)//b中所有数字当前位都为0,那么可以把题意中X的当前位构造为0(假定这一位是0),异或下来这一位就是0
18         return dfs(c,x-1);
19     return (1<<x)+min(dfs(c,x-1),dfs(d,x-1));//b中数字当前位有0也有1,那么题意中X的当前位无论取0还是1,异或下来这一位都会是1,所以这一位异或的贡献为(1<<x),然后加上c和d两组数当中更小的贡献
20 }
21 int main(){
22     ios::sync_with_stdio(false);
23     cin.tie(NULL);
24     cout.tie(NULL);
25     int n;
26     cin>>n;
27     for(int i=1;i<=n;++i){
28         int temp;
29         cin>>temp;
30         a.push_back(temp);
31     }
32     int ans=dfs(a,29);//二进制下从高位枚举,如果高位已经注定产生分支,那么就可以取低位贡献的最小值(低位贡献再大,合计也不会比高位某一位贡献大,所以取两个分支中较小的即可,较大的那一分支可以让它的高位异或为0,这样它低位的贡献也不会比另一分支要大。另一分支就可以贪心使得低位的贡献最小)
33     //(可以构造一棵深度为30,分支只有0或1的字典树)
34     cout<<ans;
35     return 0;
36 }

原文地址:https://www.cnblogs.com/ldudxy/p/12182241.html

时间: 2024-10-09 05:24:17

Codeforces Round #613 (Div. 2)D(贪心,分治)的相关文章

Codeforces Round #401 (Div. 2) E 贪心,线段树

Codeforces Round #401 (Div. 2) A 循环节 B 暴力排一下 C 标记出来,但10^5,特耿直地码了个O(n^2)的上去,最气的是在最后3分钟的时候被叉== D 从后往前贪心暴糙一下就好.比赛时一眼瞄出来了不敢写,搞不懂这样竟然不会超时.. E. Hanoi Factory 题意:n个环体,内径a[i],外径b[i],高h[i].当 a[i+1]<b[i]<=b[i+1] 时,第 i 个环体可以堆在第 i+1个环体上.求可以堆出的最高高度. tags:佩服那些大佬,

Codeforces Round #480 (Div. 2) C 贪心 D 数字、思维 E 树上倍增

Codeforces Round #480 (Div. 2) C. Posterized 题意: 给出 n 个数,都是区间 [0,255] 内的数,要你把 [0,255] 划分成多个长度 <=k 的不重叠的子区间.每个数必须包含在一个子区间内,且这个数的价值是这个子区间的左端点.要你输出这 n 数的价值,且这 n 个价值字典序要最小. tags: 首先很明显字典序最小,那对于第 i 个数 p[i] 定它的区间时,左端点肯定要尽可能小.所以我们直接枚举区间 [ p[i]-k+1, p[i] ] 定

Codeforces Round #546 (Div. 2) D 贪心 + 思维

https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则,假如u在v相邻前面,那么u和v可以交换位置,问你是队列最后一个人的时候你最前可以换到前面哪里 题解 因为相邻才能换,所以最后一个换到前面一定是一步一步向前走,所以不存在还要向后走的情况 设最后一个为u,假设前面有一个能和u换位置的集合,那么需要将这些点尽量往后移动去接u 假设前面有一个不能和u换位置的集合S,

Codeforces Round #547 (Div. 3) F 贪心 + 离散化

https://codeforces.com/contest/1141/problem/F2 题意 一个大小为n的数组a[],问最多有多少个不相交的区间和相等 题解 离散化用值来做,贪心选择较前的区间 代码 #include<bits/stdc++.h> #define M 5000005 #define ll long long #define pb push_back using namespace std; struct N{int l,r;N(int l=0,int r=0):l(l)

Codeforces Round #263 (Div. 2)C(贪心,联想到huffman算法)

数学家伯利亚在<怎样解题>里说过的解题步骤第二步就是迅速想到与该题有关的原型题.(积累的重要性!) 对于这道题,可以发现其实和huffman算法的思想很相似(可能出题人就是照着改编的).当然最后只是输出cost,就没必要建树什么的了.只要理解了huffman算法构造最优二叉树的思路,就按那么想就知道每个a[i]要加多少次了. 当然这道题没想到这些也可以找出规律的,就是一种贪心思想. #include<iostream> #include<cstdio> #include

Codeforces Round #228 (Div. 1) C 贪心

嘎嘎,今天被一些事耽误了,但是还是A了几个题目,这道题还不错 题目链接: 题意:两个人玩游戏,有N堆纸牌,纸牌上有数字,A每次只能取N堆中的 其中一个的顶部的 纸牌,B只能取N堆中的其中一个底部 的纸牌,A,B都想让自己取的和最大,问最后比分为多少 画了一下,如果某一堆里的 纸牌数量为偶数,发现其实是两个人各分一半,因为如果对方想从这里拿走本来属于自己那半部分的 较大的牌,自己完全来得及阻止的, 接下来就是奇数了,奇数 其实先手者就抢到了中间的一张牌,另外两半还是各自一半,所以 应该以每个奇数堆

Codeforces Round #257 (Div. 2)C 贪心

C. Jzzhu and Chocolate time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Jzzhu has a big rectangular chocolate bar that consists of n?×?m unit squares. He wants to cut this bar exactly k time

Codeforces Round #613 (Div. 2) D. Dr. Evil Underscores

题目:http://codeforces.com/contest/1285/problem/D 思路:从高位往低位建 \(01\;trie\) 树,从高位 dfs 当只有一个分支,当前位为 \(0\),填法唯一: 当有两个分支,当前位为 \(1\),填法不唯一,则返回较小值: #include<bits/stdc++.h> using namespace std; const int N=1e5+5; int n; int trie[N*31][2]; int cnt; void insert

Codeforces Round #613 (Div. 2)

https://codeforces.com/contest/1285 A - Mezo Playing Zoma 题意:按一系列的"LR"键,其中一些键可能被忽略执行,求最后分布的位置数量. 题解:肯定是最左和最右夹着的区间,所以统计最左的和最右的位置.最后会发现恰好就是n+1. B - Just Eat It! 题意:问是否有一段subsegment的和>=全体的和,这个subsegment不能取全体. 题解:这题里的subsegment要去掉非空前缀,或者去掉非空后缀,或者