ssoj2468设置
2015-10-31 22:04
225 查看
【题意】给n行m列数,每行取一个数组成新数,求新数中前k个最小值的异或值。
【题解】%%wwx。
这其实是一个用堆求k优解的一般思路。
先对于每个i,将元件i的a[i][1]~a[i][m]从小到大排序,再将所有元件按照其(第2~第m种设置与第1种设置的差值)多关键字从小到大排序(共m-1个关键字)。
现在开始,我们将排在第i位的元件称为元件i,其第j小的设置称为元件i的设置j。
那么我们知道,最小的方案肯定是所有元件都设置为1。由于其有一些特殊,我们先抛开这个方案。(实际上不抛开也是可行的)
我们知道,次小的方案是(2,1,1,1…),我们以此为起点s,由较优方案扩展较劣方案,对于每一个方案,我们记录其最后被扩展的位置(对于s,这个位置为1)。在已经得到前t优的方案时,当前所有方案中还未扩展的最好的方案x(其最后扩展位置为i),就是第t+1优。
从方案x,我们可以扩展出几个较劣解:
1、 i<n:将i+1号元件设置为2(扩展位置为i+1)
2、 x的第i个元件设置为2且i<n:将i号元件设置为1,i+1号元件设置为2(扩展位置为i+1)
3、 x的第i个元件设置不为m:将i号元件设置增加1(扩展位置为i)
由此,每个解都可由唯一的优于它的解扩展得来。
用堆维护当前所有解即可。
【代码】
【题解】%%wwx。
这其实是一个用堆求k优解的一般思路。
先对于每个i,将元件i的a[i][1]~a[i][m]从小到大排序,再将所有元件按照其(第2~第m种设置与第1种设置的差值)多关键字从小到大排序(共m-1个关键字)。
现在开始,我们将排在第i位的元件称为元件i,其第j小的设置称为元件i的设置j。
那么我们知道,最小的方案肯定是所有元件都设置为1。由于其有一些特殊,我们先抛开这个方案。(实际上不抛开也是可行的)
我们知道,次小的方案是(2,1,1,1…),我们以此为起点s,由较优方案扩展较劣方案,对于每一个方案,我们记录其最后被扩展的位置(对于s,这个位置为1)。在已经得到前t优的方案时,当前所有方案中还未扩展的最好的方案x(其最后扩展位置为i),就是第t+1优。
从方案x,我们可以扩展出几个较劣解:
1、 i<n:将i+1号元件设置为2(扩展位置为i+1)
2、 x的第i个元件设置为2且i<n:将i号元件设置为1,i+1号元件设置为2(扩展位置为i+1)
3、 x的第i个元件设置不为m:将i号元件设置增加1(扩展位置为i)
由此,每个解都可由唯一的优于它的解扩展得来。
用堆维护当前所有解即可。
【代码】
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #define ll long long using namespace std; const int maxn=300005; int n,m,k; ll ans=0,b[maxn]; struct data{ ll *v; bool operator<(const data&fn)const{ for(int i=1;i<m;++i)if(v[i]!=fn.v[i])return v[i]<fn.v[i];//按字典序排序 return 0; } }a[maxn]; struct da{ ll w; int h,l; da(ll w,int h,int l):w(w),h(h),l(l){}; bool operator >(const da&fn)const{ return w>fn.w; } }; inline int get(){ char c;while(!isdigit(c=getchar())); int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48; return v; } priority_queue< da,vector<da>,greater<da> >q; int main(){ n=get();m=get();k=get(); for(int i=1;i<=n;++i){ a[i].v=b+(i-1)*m;//可以根据m来分配内存 for(int j=0;j<m;++j)a[i].v[j]=get(); sort(a[i].v,a[i].v+m);ans+=a[i].v[0]; for(int j=m-1;j>0;--j)a[i].v[j]-=a[i].v[j-1];//差量 } sort(a+1,a+1+n); q.push(da(ans+a[1].v[1],1,1));//大根堆维护 while(--k){ da x=q.top();q.pop(); ans^=x.w; if(x.l<m-1){ //三种转移 q.push(da(x.w+a[x.h].v[x.l+1],x.h,x.l+1)); } if(x.l>0&&x.h<n){ q.push(da(x.w+a[x.h+1].v[1],x.h+1,1)); } if(x.l==1&&x.h<n){ q.push(da(x.w-a[x.h].v[x.l]+a[x.h+1].v[1],x.h+1,1)); } } printf("%lld\n",ans); return 0; }
相关文章推荐
- ArcGIS for Server 10.3.X 新型紧凑型缓存的解读和应用
- BestCoder Round #61 (div.2)
- HDU5512(水题~)
- 数据挖掘算法之协同过滤算法
- BestCoder Round #61 1002 Game
- 【系统性能优化】(四)数据库连接池
- shell 脚 本 练 习 题(四)
- 9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路
- Subline快捷键
- wpf之datagrid 序号列
- hive数据倾斜的解决方案
- 基于fab自动化部署
- [leetcode] Bulls and Cows
- wpf之IValueConverter接口
- java web开发中,如何查看JSP和Servlet版本
- 【系统性能优化】(三)数据库访问优化
- 单例模式
- Node.js面试题
- groovy install,gvm,groovysh简述(转)
- iScroll.js 向上滑动异步加载数据回弹问题