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
输出一个整数表示可能的最小值
每位分别考虑,f[i][j]表示前i个数,异或和这一位为j,此时这一位至少有几个1
如果某个位置已被确定,直接计算,否则可以选择填0或1
f[i][0]=min(f[i-1][0],f[i-1][1])
f[i][1]=min(f[i-1][0],f[i-1][1])+1
可以发现这样推两步或以上值就不会变了,因此相邻多个未确定的数可以当做一个处理
#include<bits/stdc++.h> typedef long long i64; const int N=1e6+7; int n,m; struct pos{ int x,y; bool operator<(const pos&w)const{return x<w.x;} }ps[N]; i64 f[33][2]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i)scanf("%d%d",&ps[i].x,&ps[i].y); std::sort(ps+1,ps+m+1); int px=0; for(int t=0;t<=30;++t)f[t][1]=1ll<<60; for(int i=1;i<=m;++i){ int x=ps[i].x,y=ps[i].y; int d=x-px-1; if(d)for(int t=0;t<=30;++t){ i64 f0=f[t][0],f1=f[t][1]; f[t][0]=std::min(f0,f1); f[t][1]=std::min(f0,f1)+1; } for(int t=0;t<=30;++t){ int b=y>>t&1; i64 f0=f[t][0],f1=f[t][1]; if(b){ f[t][0]=f1; f[t][1]=f0+1; }else{ f[t][0]=f0; f[t][1]=f1+1; } } px=x; } i64 s=0; for(int t=0;t<=30;++t)s+=std::min(f[t][0],f[t][1])<<t; printf("%lld\n",s); return 0; }