poj 3274 自定义排序
2015-09-03 22:13
295 查看
题意:n头牛站一排,每个牛有k个属性,每个属性有两种取值:1或0。(1表示拥有该属性,0表示没有),用位来保存属性,属性≤30个。要求找一个牛的最长连续队伍(子段),这个队伍中拥有每个属性的牛的个数相同。
思路:看数据量n^2肯定不行,想不出来,看了眼官方的解法大致明白。
Consider the partial sum sequence of each of the k features built by taking the sum of all the values up to position i. The problem is equivalent to:Given an array s
[k], find i,j, with the biggest separation for which s[ i ][l]-s[j][l] is constant for
all l.
The problem is now to do this efficiently. Notice that s[ i ][l]-s[j][l] being constant for all l is equivalent to s[ i ][l]-s[j][l]=s[ i ][1]-s[j][1] for all l, which can be rearranged to become s[ i ][l]-s[ i ][1]=s[j][l]-s[j][1] for all l. Therefore, we
can construct another array a
[k] where a[ i ][j]=s[ i ][j]-s[ i ][1] and the goal is to find i and j with the biggest separation for which a[ i ][l]=a[j][l] for all l.
This can be done by sorting all the a[ i ] entries, which takes O(nklogn) time (although in practice rarely will all k elements be compared). Another alternative is to go by hashing, giving an O(nk) solution. Both solutions are fairly straightforward once the
final array is constructed.
翻译过来就是:我们记录一个sum[i][j]数组,记录前i个牛的第j个属性和。我们用我们需要寻找sum中的两行,这两行中所有对应位的差都相等,则这段牛是符合条件的答案之一。所以我们用另一数组,来记录sum中对应行的各个元素之间的差异。我们记录c[i][j] = sum[i][j] - sum[i][0]这样只要c的两行对应相等即可。然后我们就找相隔最远的两个c的相等行即为所求。
思路:看数据量n^2肯定不行,想不出来,看了眼官方的解法大致明白。
Consider the partial sum sequence of each of the k features built by taking the sum of all the values up to position i. The problem is equivalent to:Given an array s
[k], find i,j, with the biggest separation for which s[ i ][l]-s[j][l] is constant for
all l.
The problem is now to do this efficiently. Notice that s[ i ][l]-s[j][l] being constant for all l is equivalent to s[ i ][l]-s[j][l]=s[ i ][1]-s[j][1] for all l, which can be rearranged to become s[ i ][l]-s[ i ][1]=s[j][l]-s[j][1] for all l. Therefore, we
can construct another array a
[k] where a[ i ][j]=s[ i ][j]-s[ i ][1] and the goal is to find i and j with the biggest separation for which a[ i ][l]=a[j][l] for all l.
This can be done by sorting all the a[ i ] entries, which takes O(nklogn) time (although in practice rarely will all k elements be compared). Another alternative is to go by hashing, giving an O(nk) solution. Both solutions are fairly straightforward once the
final array is constructed.
翻译过来就是:我们记录一个sum[i][j]数组,记录前i个牛的第j个属性和。我们用我们需要寻找sum中的两行,这两行中所有对应位的差都相等,则这段牛是符合条件的答案之一。所以我们用另一数组,来记录sum中对应行的各个元素之间的差异。我们记录c[i][j] = sum[i][j] - sum[i][0]这样只要c的两行对应相等即可。然后我们就找相隔最远的两个c的相等行即为所求。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <cstdlib> using namespace std; #define clc(s,t) memset(s,t,sizeof(s)) #define INF 0x3fffffff #define N 100005 int n,k; struct node{ int id; int d[32]; }s ; int cmp(node a,node b){ for(int i = k-1;i>=0;i--){ if(a.d[i] < b.d[i]) return 1; if(a.d[i] > b.d[i]) return 0; } return a.id < b.id; } int equal(int a,int b){ for(int i = k-1;i>=0;i--) if(s[a].d[i] != s[b].d[i]) return 0; return 1; } int main(){ int i,j,x,res=0; scanf("%d %d",&n,&k); for(i = 1;i<=n;i++){ scanf("%d",&x); s[i].id = i; for(j = 0;j<k;j++){ s[i].d[j] = x&1; if(i>1) s[i].d[j] += s[i-1].d[j]; x>>=1; } } for(i = 1;i<=n;i++){ x = s[i].d[0]; for(j = 0;j<k-1;j++) s[i].d[j] -= s[i].d[j+1]; s[i].d[k-1] -= x; } clc(s[0].d,0); s[0].id = 0; sort(s,s+n+1,cmp); for(i = 0;i<=n;){ for(j = i+1;j<=n&&equal(i,j);j++); res = max(res,s[j-1].id-s[i].id); i = j; } printf("%d\n",res); return 0; }
相关文章推荐
- SQL审核自动化
- 小游戏
- ARM 开发板嵌入式linux系统与主机PC通过串口传输文件
- 合并多个表格数据的代码
- Linux PCI中断:冲突和传递,两张相同PCI卡的冲突
- Java的ProtoBuf
- 数据库三大范式
- .net C# 中的APM异步编程方式
- jsp文件上传
- Java VM for IOS
- javascript广告漂浮效果代码
- C++中string使用
- 周鸿祎:给那些仍旧在公司混日子的人
- 技嘉主板BIOS恢复方法
- 深扒脸书中国工程师带人进公司蹭饭赚钱被开除
- poj 2184 Cow Exhibition(dp之01背包变形)
- Processing - 练习(3)"飞碟追踪" - (渐进、延迟效果)
- Fibonacci数列与跳台阶问题
- HUD Average 5353模拟
- C++基础---函数的参数