| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
35544K 141ms 内存快要爆了2333【附代妈和思路】其实呢这个每一步都可以唯一确定的。。。搜索剪纸或者dp啥的还是算了吧= =
最简单的从最后一列推第一列是trivial的,就是把0排在前面,1排在后面~
然后再深入思考以下就可以发现,后面的每一列都差不多,只不过要利用前面的信息,不能破坏已经排好的序,我们可以存放一个order【N】数组,然后记录所有区间断点(我代妈里的intv【】)。在这些断点分割出来的每个区间里来一个小的计数排序,即把0放在前面,1放在后面,重新更新order数组,这样扫描一遍就可以完成,总复杂度是线性。之后下面一行的zeroone值,可以根据这个数组唯一确定了,一共进行N-1次,因此总复杂度为平方级。
#include <iostream>
#include <stdio.h>
using namespace std;
int zeroone[3003][3003];
void print(int N){
for(int j = 0; j < N; j++){
for(int i = 0; i < N; i++){
cout << zeroone[i][j] << " ";
}
cout << endl;
}
}
int main() {
int N;
scanf("%d", &N);
for(int i = 0; i < N; i++){
scanf("%d", &zeroone[N-1][i]);
}
bool intv[3004] = {false};
intv[0] = true; intv[N] = true;//开始就一个区间,[0,N)
int order[3003];
for(int i = 0; i < N; i++) order[i] = i;
for(int i = 0; i < N-1; i++){
int from = i==0? N-1: i-1;
int start = 0;
int end;
int temp[3004];
while(1){
//print(N);
//for(int ii = 0; ii < N; ii++) cout << order[ii] << " "; cout << endl;
//cout << endl;
for(int j = start+1; ; j++){
if(intv[j]) {
end = j;
break;
}
}
if(end - start == 1){
zeroone[i][start] = zeroone[from][order[start]];
}
else{
int offset = 0;
int temp_pl = start;
for(int ii = start; ii < end; ii++){
if(zeroone[from][order[ii]] == 0){
order[start+offset] = order[ii];
offset ++;
}
else{
temp[temp_pl] = order[ii];
temp_pl ++;
}
}
intv[start+offset] = true;
for(int ii = 0; ii < temp_pl-start; ii++){
order[start+offset+ii] = temp[ii+start];
}
for(int ii = start; ii < end; ii++){
zeroone[i][ii] = zeroone[from][order[ii]];
}
}
if(end == N) break;
start = end;
}
}
for(int i = 0; i < N; i++) printf("%d ", zeroone[i][0]);
printf("\n");
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator