4245: [ONTAK2015]OR-XOR

4245: [ONTAK2015]OR-XOR

https://www.lydsy.com/JudgeOnline/problem.php?id=4245

 1 /*
 2 要求分成m份,总价值为a1|a2|a3...,总价值最小,ai为第i份的异或和。
 3
 4 首先预处理异或和。
 5 根据贪心的思想,高位最好是0。
 6 于是从高位往低位枚举,看一下每一位是否可以为0。
 7 如果当前这一位可以为0,每一份的(异或和)(或)起来都是0,所以每一份异或和的这一位不能有1
 8 那么一个点可以成为分割点当且仅当这个点的sum值的这一位为0,然后统计有多少个点的sum为0
 9 如果个数>=m且这一位上的所有1为偶数个(sum[n]&(1LL<<i)==0),那么这一位可以为0,然后对于那些不能成为分割点的点,标记不能再成为分割点。
10 不然会使这一位不为0了。
11 如果不能0,那就为1了,ans更新。
12 */
13 #include<bits/stdc++.h>
14 using namespace std;
15 typedef long long LL;
16
17 inline LL read() {
18     LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1;
19     for (;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f;
20 }
21
22 const int N = 500100;
23 LL a[N],sum[N],flag[N];
24
25 int main() {
26     int n,m;cin >> n >> m;
27     for (int i=1; i<=n; ++i)
28         a[i] = read(),sum[i] = sum[i-1] ^ a[i];
29     LL ans = 0;
30     for (int i=62; i>=0; --i) { // 看第i位能否为0
31         int cnt = 0;
32         for (int j=1; j<=n; ++j) { // 统计有多少个右端点满足条件
33             if (!flag[j] && (sum[j]&(1LL<<i))==0) cnt++;
34         }
35         if (cnt >= m && (sum[n]&(1LL<<i))==0) { // 如果这一位可以放0。----   少加了对花括号。。。
36             for (int j=1; j<=n; ++j)  // 对所有不可以成为右端点的点打标记
37                 if ((sum[j]&(1LL<<i)) != 0) flag[j] = 1;
38         }
39         else ans |= (1LL << i);
40     }
41     cout << ans;
42     return 0;
43 }

原文地址:https://www.cnblogs.com/mjtcn/p/9756211.html

时间: 2024-10-12 10:38:50

4245: [ONTAK2015]OR-XOR的相关文章

BZOJ 4245: [ONTAK2015]OR-XOR 贪心

4245: [ONTAK2015]OR-XOR Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 567  Solved: 312[Submit][Status][Discuss] Description 给定一个长度为n的序列a[1],a[2],...,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or ... or c[m].请求出总费用的最小值. Input 第一行包含

BZOJ 4245 ONTAK2015 OR-XOR

题目大意:给定一个长度为n的序列,要求分成m段,使得每段异或和的或值最小 求出前缀异或和后从大到小按位确定,如果某一位上有至少m个数是0且第n个数是0,那么这一位就可以是0,同时将所有是1的数字标记为不可选 时间复杂度O(nlogai) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 500500 using namespace s

【BZOJ-4245】OR-XOR 按位贪心

4245: [ONTAK2015]OR-XOR Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 486  Solved: 266[Submit][Status][Discuss] Description 给定一个长度为n的序列a[1],a[2],...,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or ... or c[m].请求出总费用的最小值. Input 第一行包含

【BZOJ4245】[ONTAK2015]OR-XOR 贪心

[BZOJ4245][ONTAK2015]OR-XOR Description 给定一个长度为n的序列a[1],a[2],...,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or ... or c[m].请求出总费用的最小值. Input 第一行包含两个正整数n,m(1<=m<=n<=500000),分别表示序列的长度和需要划分的段数. 第一行包含n个整数,其中第i个数为a[i](0<=a[i]<=

bzoj 2337: [HNOI2011]XOR和路径

Description Input Output Sample Input Sample Output HINT Source Day2 终于把这个史前遗留的坑给填了... 首先异或的话由位无关性,可以按位处理... 那么对于每一位,设f[i]表示从i出发第一次到达n且xor和为1的概率,out[i]为i的出边,那么转移就比较容易了... if(w(i,j)&xxx) f[i]+=(1-f[j)/out[i];// 这条边该位为1,需要xor上0,xor和才为1 else f[i]+=f[j]/

【BZOJ】2337: [HNOI2011]XOR和路径

[算法]期望+高斯消元 [题解]因为异或不能和期望同时运算,所以必须转为加乘 考虑拆位,那么对于边权为1取反,边权为0不变. E(x)表示从x出发到n的路径xor期望. 对于点x,有E(x)=Σ(1-E(y))(边权1)||E(y)(边权0)/t[x]  t[x]为x的度. 那么有n个方程,整体乘上t[x]确保精度,右项E(x)移到左边--方程可以各种变形. 每次计算完后*(1<<k)就是贡献. 逆推的原因在于n不能重复经过,而1能重复经过,所以如果计算"来源"不能计算n,

421. Maximum XOR of Two Numbers in an Array

Given a non-empty array of numbers, a0, a1, a2, - , an-1, where 0 ≤ ai < 231. Find the maximum result of ai XOR aj, where 0 ≤ i, j < n. Could you do this in O(n) runtime? Example: Input: [3, 10, 5, 25, 2, 8] Output: 28 Explanation: The maximum resul

Codeforces 617 E. XOR and Favorite Number

题目链接:http://codeforces.com/problemset/problem/617/E 一看这种区间查询的题目,考虑一下莫队. 如何${O(1)}$的修改和查询呢? 令${f(i,j)}$表示区间${\left [ l,r \right ]}$内数字的异或和. 那么:${f(l,r)=f(1,r)~~xor~~f(1,l-1)=k}$ 记一下前缀异或和即可维护. 1 #include<iostream> 2 #include<cstdio> 3 #include&l

Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题是线段树成段更新,但是不能直接更新,不然只能一个数一个数更新.这样只能把每个数存到一个数组中,长度大概是20吧,然后模拟二进制的位操作.仔细一点就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>