题目
思路
题意是说将一组数排列成另外一组数,排序的方式是每次取出3个连续的的数字,然后abc可以cab,也就整体右移,超出位置的到最左边。
问能否排列成目标数组。
额,实在是不会做。在网上找到了好几个人的题解,稍加重写并比较性能好了。
好像和树状数组有关。
如代码区所示。
代码
第一种方法,用时0.9s:
by Per Austrin
//Sample solution for the Bread Sorting problem in NCPC 2012 by Per Austrin
//Rewrite by Weiping Huang
//0.9s
#include <stdio.h>
#include <algorithm>
using namespace std;
int n;
char text[600005];
int A[100005], B[100005], C[100005];
void Readin(int * num) {
gets(text);
int sum = 0, k = 0;
for (int i = 0; text[i] != '\0'; i++) {
if (text[i] == ' ') {
num[k++] = sum;
sum = 0;
}
else {
sum = 10 * sum + (text[i] & 15);
}
}
num[k] = sum;
//for (int i = 0; i < n; i++) scanf("%d", num + i);
}
int inversions(int n, int * N) {
if (n < 2) return 0;
int m = n / 2;
int r = inversions(m, N) + inversions(n - m, N + m);
int x = 0, y = m;
while (x < m && y < n) {
if (N[y] < N[x]) {
r += m - x;
y++;
}
else x++;
}
sort(N, N + n);
return r;
}
int main() {
while (~scanf("%d\n", &n)) {
Readin(A);
Readin(B);
for (int i = 0; i < n; i++) C[B[i]] = i;
for (int i = 0; i < n; i++) A[i] = C[A[i]];
printf("%sossible\n", inversions(n, A) & 1 ? "Imp" : "P");
}
return 0;
}
第二种方法,用时0.06s:
By Lukáš Poláček (lukasP)
//Sample solution for the Bread Sorting problem in NCPC 2012 by Lukáš Poláček (lukasP)
//Rewrite by Weiping Huang
//0.06s
#include <stdio.h>
#include <string.h>
int n;
char text[600005];
bool seen[100005];
int A[100005], B[100005];
void ReadinA(int * num) {
gets(text);
int sum = 0, k = 0;
for (int i = 0; text[i] != '\0'; i++) {
if (text[i] == ' ') {
num[k++] = sum;
sum = 0;
}
else {
sum = 10 * sum + (text[i] & 15);
}
}
num[k] = sum;
//for (int i = 0; i < n; i++) scanf("%d", num + i);
}
void ReadinB(int * num) {
gets(text);
int sum = 0, k = 0;
for (int i = 0; text[i] != '\0'; i++) {
if (text[i] == ' ') {
num[A[k++] - 1] = sum;
sum = 0;
}
else {
sum = 10 * sum + (text[i] & 15);
}
}
num[A[k] - 1] = sum;
//for (int i = 0; i < n; i++) scanf("%d", num + i);
}
int main() {
while (~scanf("%d\n", &n)) {
ReadinA(A);
ReadinB(B);
memset(seen, false, sizeof(bool) * n);
int swaps = n;
for (int i = 0; i < n; i++) {
if (!seen[i]) {
swaps--;
for (int j = i; !seen[j]; j = B[j] - 1) seen[j] = true;
}
}
printf("%sossible\n", swaps & 1 ? "Imp" : "P");
}
return 0;
}
第三种方法,用时0.51s:
By Lukáš Poláček (lukasP)
//Sample solution for the Bread Sorting problem in NCPC 2012 by Lukáš Poláček (lukasP)
//Rewrite by Weiping Huang
//0.51s
#include <stdio.h>
#include <string.h>
#include <math.h>
int n;
char text[600005];
int A[100005], B[100005];
struct Buckets {
int n, b_size;
int s[100005];
bool t[100005];
void clear(int n) {
b_size = int(sqrt((double)n) + 1.1);
for (int i = (n + b_size - 1) / b_size - 1; i >= 0; i--) s[i] = 0;
for (int i = n - 1; i >= 0; i--) t[i] = false;
}
void update(int pos) {
t[pos] = true;
s[pos / b_size]++;
}
int query(int val) {
int b_ind = val / b_size;
int res = 0;
for (int i = 0; i < b_ind; i++) res += s[i];
for (int i = b_ind * b_size; i < val; i++) res += t[i];
return res;
}
}s, t;
void Readin(int * num) {
gets(text);
int sum = 0, k = 0;
for (int i = 0; text[i] != '\0'; i++) {
if (text[i] == ' ') {
num[k++] = sum - 1;
sum = 0;
}
else {
sum = 10 * sum + (text[i] & 15);
}
}
num[k] = sum - 1;
//for (int i = 0; i < n; i++) scanf("%d", num + i);
}
int main() {
while (~scanf("%d\n", &n)) {
long long ia = 0, ib = 0;
s.clear(n);
t.clear(n);
memset(A, 0, sizeof(int) * n);
memset(B, 0, sizeof(int) * n);
Readin(A);
for (int i = 0; i < n; i++) {
ia += i - s.query(A[i]);
s.update(A[i]);
}
Readin(B);
for (int i = 0; i < n; i++) {
ib += i - t.query(B[i]);
t.update(B[i]);
}
printf("%sossible\n", ((ia & 1) != (ib & 1)) ? "Imp" : "P");
}
return 0;
}
第四种方法,用时0.33s:
By Andreas Björklund
//Sample solution for the Bread Sorting problem in NCPC 2012 by Andreas Björklund
//Rewrite by Weiping Huang
//0.33s
#include <stdio.h>
#include <string.h>
#include <math.h>
int n, tpn;
char text[600005];
int A[1 << 17], B[1 << 17];
int sum1, sum2;
int count(int* T, int who)
{
int ix = who;
int cnt = 0;
while (ix <= tpn) {
int inc = ix & -ix;
cnt ^= (ix <= who) ? T[ix - 1] : 0;
T[ix - 1] ^= (ix >= who);
ix ^= inc;
ix |= (inc << 1);
}
return cnt & 1;
}
void ReadinAndCount() {
sum1 = sum2 = 0;
gets(text);
int sum = 0;
for (int i = 0; text[i] != '\0';) {
if (text[i] == ' ') {
i++;
while (text[i] == ' ') i++;
sum1 ^= count(A, sum);
sum = 0;
}
else {
sum = 10 * sum + (text[i] & 15);
i++;
}
}
sum1 ^= count(A, sum);
sum = 0;
gets(text);
for (int i = 0; text[i] != '\0';) {
if (text[i] == ' ') {
i++;
while (text[i] == ' ') i++;
sum2 ^= count(B, sum);
sum = 0;
}
else {
sum = 10 * sum + (text[i] & 15);
i++;
}
}
sum2 ^= count(B, sum);
sum = 0;
}
int main() {
while (~scanf("%d\n", &n)) {
tpn = 1;
while (tpn < n) tpn <<= 1;
for (int i = 0; i < n; i++) A[i] = B[i] = 0;
ReadinAndCount();
printf("%sossible\n", sum1 != sum2 ? "Imp" : "P");
}
return 0;
}