bzoj5108 [CodePlus2017]可做题 位运算dp+离散

[CodePlus2017]可做题

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 87  Solved: 63
[Submit][Status][Discuss]

Description

qmqmqm希望给sublinekelzrip出一道可做题。于是他想到了这么一道题目:给一个长度为n的非负整数序列ai,你需

要计算其异或前缀和bi,满足条件b1=a1,bi=bi?1 xor ai(i≥2).但是由于数据生成器出现了问题,他生成的序列a

的长度特别长,并且由于内存空间不足,一部分ai已经丢失了,只剩余m个位置的元素已知。现在qmqmqm找到你,

希望你根据剩余的ai,计算出所有可能的a序列对应的b序列中∑=bi(1<=i<=N)的最小值。

Input

输入第一行两个非负整数n,m,分别表示原始序列a的长度及剩余元素的个数。

之后m行,每行2个数i,ai,表示一个剩余元素的位置和数值。

1<=N<=10^9,0<=M<=Min(n,10^5),0<=ai<=10^9

注意未知的 ai 可以超过已知 ai 的范围。

保证输入中所有的 i 不同,且满足 1 ≤ i ≤ n。

Output

输出一个整数表示可能的最小值

Sample Input

5 3
4 0
3 7
5 0

Sample Output

7
已知的 a 序列为: X, X, 7, 0, 0, 其中X表示这个位置丢失了。一种可能的 a 序列为
0, 7, 7, 0, 0, 对应的 b 序列为 0, 7, 0, 0, 0, 和最小为 7。可以证明不存在和更小的情况

HINT

来自 CodePlus 2017 11 月赛,清华大学计算机科学与技术系学生算法与竞赛协会 荣誉出品。

Credit:idea/卢政荣 命题/卢政荣 验题/何昊天

Git Repo:https://git.thusaac.org/publish/CodePlus201711

本次比赛的官方网址:cp.thusaac.org

感谢腾讯公司对此次比赛的支持。

Source

题解,各个位置上的位运算是相互不影响的,

所以可以分开来dp,然后,对于相差两个即以上的可以抵消,

那么是需要特殊处理,一个的话默认为前面的或者0,数据范围比较大,需要离散化。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdio>
 6
 7 #define ll long long
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch>‘9‘||ch<‘0‘){if (ch==‘-‘) f=-1;ch=getchar();}
13     while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
14     return x*f;
15 }
16
17 int n,m,b[300005],pre;
18 ll ans,f[300005][2];
19 struct node{int id,val;}a[300005];
20 bool cmp(node a,node b){return a.id<b.id;}
21 int main()
22 {
23     n=read();m=read();n=0;
24     for (int i=1;i<=m;i++)
25         a[i].id=read(),a[i].val=read();
26     sort(a+1,a+m+1,cmp);
27     for (int i=1;i<=m;i++)
28     {
29         if (a[i].id-pre-1>=2){b[++n]=-1;b[++n]=-1;b[++n]=a[i].val;}
30         else if (a[i].id-pre==2){b[++n]=-1;b[++n]=a[i].val;}
31         else b[++n]=a[i].val;
32         pre=a[i].id;
33     }
34     f[0][1]=1e15;f[0][0]=0;
35     for (int p=0;p<=30;p++)
36     {
37         for (int i=1;i<=n;i++)
38             if (b[i]<0)
39             {
40                    f[i][1]=min(f[i-1][0]+(1<<p),f[i-1][1]+(1<<p));
41                 f[i][0]=min(f[i-1][1],f[i-1][0]);
42             }
43             else
44             {
45                 if (b[i]&(1<<p))
46                 {
47                     f[i][1]=f[i-1][0]+(1<<p);
48                     f[i][0]=f[i-1][1];
49                 }
50                 else
51                 {
52                     f[i][1]=f[i-1][1]+(1<<p);
53                     f[i][0]=f[i-1][0];
54                 }
55             }
56         ans+=min(f[n][0],f[n][1]);
57     }
58     printf("%lld",ans);
59 }

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8119397.html

时间: 2024-08-04 03:52:49

bzoj5108 [CodePlus2017]可做题 位运算dp+离散的相关文章

剑指offer-面试题65-不用加减乘除做加法-位运算

/* 题目: 在不使用加减乘除的前提下,计算两个整数之和. 思路: 不能使用加减乘除则只能考虑位运算. x=num1^num2,则为抹掉进位的结果. y=num1&num2,为只有进位的结果. (y<<1)&x,直到不产生进位. */ #include<iostream> #include<cstring> #include<vector> #include<algorithm> #include<map> using

【bzoj5108】[CodePlus2017]可做题 拆位+乱搞

题目描述 给出一个长度为 $m$ 的序列 $a$ ,编号为 $a_1\sim a_m$,其中 $n$ 个位置的数已经确定,剩下的位置的数可以任意指定.现在令 $b$ 表示 $a$ 的前缀异或和,求 $\sum\limits_{i=1}^mb_i$ 的最小值. 输入 输入第一行两个非负整数n,m,分别表示原始序列a的长度及剩余元素的个数. 之后m行,每行2个数i,ai,表示一个剩余元素的位置和数值. 1<=N<=10^9,0<=M<=Min(n,10^5),0<=ai<=

bzoj4300 绝世好题(位运算+DP)

为什么要写这道题呢?因为它是"绝世好题". 题意:给定n个数,在其中找出一段子序列b,使得b[i]&b[i-1]!=0,求出满足条件的最长子序列长度. 输入:第一行:一个整数n,表示数列的个数. 第二行:n个整数,表示数列a. 输出:一行,一个整数,表示最长的子序列长度. 输入样例: 3 1 2 3 输出样例: 2 解析:若b[i]&b[i-1]!=0,即b[i]与b[i-1]在二进制下有一位相同且都为1.那么设dp[i]表示前i个数所能达到的最长子序列长度,那么在转移

【CF908E】New Year and Entity Enumeration 位运算+DP

[CF908E]New Year and Entity Enumeration 题意:给定$M=2^m-1$,我们称一个集合S是好的,当且仅当它满足:1.$\forall a\in S,a \mathrm{xor} M \in S$,2.$\forall a,b\in S,a \mathrm{and} b \in S$,3.\forall a\in S,a\le M. 现在给定集合T,求有多少个好的集合S,满足T是S的子集. m<=1000,|T|<=50. 题解:显然有了与和取反以后,我们还

51nod 1406 位运算/dp

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1406 1406 与查询 题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 有n个整数.输出他之中和x相与之后结果为x的有多少个.x从0到1,000,000 Input 第一行输入一个整数n.(1<=n<=1,000,000). 第二行有n个整数a[0],a[1],a[2],...a[n-1

leetcode 201. Bitwise AND of Numbers Range(位运算,dp)

Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive. For example, given the range [5, 7], you should return 4. 题解:如果m==n,那么答案就是m. 如果m<n,那么二进制最右边一位在最后的结果中肯定是0,那么就可以转化成子问题: rangeBi

位运算+枚举

位运算http://c.biancheng.net/cpp/html/101.html 在很多情况下(比如翻棋子)在搜索时涉及大量枚举往往导致超时,位运算则很好地解决了这个问题,方便又快捷 HDU  1882   Strange Billboard http://acm.hdu.edu.cn/showproblem.php?pid=1882 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot

[位运算] [搜索] [递推优化] [计算几何] TEST 2016.7.15

NOIP2014 提高组模拟试题 第一试试题 题目概况: 中文题目名称 合理种植 排队 科技节 源程序文件名 plant.pas/.c/.cpp lineup.pas/.c/.cpp scifest.pas/.c/.cpp 输入文件名 plant.in lineup.in scifest.in 输出文件名 plant.out lineup.out scifest.out 每个测试点时限 1s 1s 1s 测试点数目 10 10 10 每个测试点分值 10 10 10 内存上限 128MB 128

求集合中选一个数与当前值进行位运算的max

求集合中选一个数与当前值进行位运算的max 这是一个听来的神仙东西. 先确定一下值域把,大概\(2^{16}\),再大点也可以,但是这里就只是写写,所以无所谓啦. 我们先看看如果暴力求怎么做,位运算需要给定\(01/10,00,11\)的关系,总共\(8\)种. 如果是暴力的话,我们的方法有两种, 第一种是比较喜闻乐见的, 我们对于当前数\(x\),暴力计算所有存在的数\(a_i\)中,\(x\oplus a_i\)的最大值,这样的复杂度是\(O(2^{16})\)的. 另外一种也是不难考虑到的