#include <cstdio>
//#define DEBUG 1
/*
* Zadanie: per
* Autor rozwiązania: Jan Horodecki
*/
int l_inwersji;
void zmien(int i, int x, int drzewo[]){
while(i>0){
drzewo[i]+=x;
i/=2;
}
}
int mniejszeniz(int i,int drzewo[]){
int wyn=0;
while(i!=1){
if(i%2==1){
wyn+=drzewo[i-1];
}
i/=2;
}
return wyn;
}
long long znajdz(int pos,long long up_sumk,int inw,int n, long long k,int drzewo[],int drz_s){
// #ifdef DEBUG
// for(int i=0;i<pos;i++)printf(" ");
// printf("pos=%d up_sumk=%lld inw=%d n=%d k=%lld drz_s=%d ",pos,up_sumk,inw,n,k,drz_s);
// for (int i=drz_s;i<2*drz_s;i++){
// printf("%d ",drzewo[i]);
// }
// printf("\n");
//#endif
long long sumk=0;
if(pos==n){
if(inw==l_inwersji){
//#ifdef DEBUG
// printf("%lld +1 \n",up_sumk);
//#endif
if(up_sumk+1==k)return -1;
return 1;
}
}
//optymalizacje
if(true){
if(inw>l_inwersji)return 0;
int q=n-pos;
if(inw+q*(q-1)/2<l_inwersji)return 0;
}
//koniec opt
for(int i=drz_s ; i<drz_s+n; i++){
if(drzewo[i]==0){
zmien(i,1,drzewo);
int akt_inw=inw;
akt_inw+=i-drz_s-mniejszeniz(i,drzewo);
int zwr=znajdz(pos+1,up_sumk+sumk,akt_inw,n,k,drzewo,drz_s);
if(zwr==-1){
drzewo[pos]=i-drz_s+1;
return -1;
}
sumk+=zwr;
zmien(i,-1,drzewo);
}
}
return sumk;
}
int main(){
int drzewo[524290]={},n,d_s=1;
long long k;
scanf("%d%lld",&n,&k);
if( (n*(n-1)/2) %2 == 1 ){
printf("NIE");
return 0;
}
l_inwersji=n*(n-1)/4;
while(d_s<n){
d_s=d_s<<1;
}
if(znajdz(0,0,0,n,k,drzewo,d_s)==-1){
printf("TAK\n");
for(int i=0;i<n;i++){
printf("%d ",drzewo[i]);
}
}else{
printf("NIE");
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include <cstdio> //#define DEBUG 1 /* * Zadanie: per * Autor rozwiązania: Jan Horodecki */ int l_inwersji; void zmien(int i, int x, int drzewo[]){ while(i>0){ drzewo[i]+=x; i/=2; } } int mniejszeniz(int i,int drzewo[]){ int wyn=0; while(i!=1){ if(i%2==1){ wyn+=drzewo[i-1]; } i/=2; } return wyn; } long long znajdz(int pos,long long up_sumk,int inw,int n, long long k,int drzewo[],int drz_s){ // #ifdef DEBUG // for(int i=0;i<pos;i++)printf(" "); // printf("pos=%d up_sumk=%lld inw=%d n=%d k=%lld drz_s=%d ",pos,up_sumk,inw,n,k,drz_s); // for (int i=drz_s;i<2*drz_s;i++){ // printf("%d ",drzewo[i]); // } // printf("\n"); //#endif long long sumk=0; if(pos==n){ if(inw==l_inwersji){ //#ifdef DEBUG // printf("%lld +1 \n",up_sumk); //#endif if(up_sumk+1==k)return -1; return 1; } } //optymalizacje if(true){ if(inw>l_inwersji)return 0; int q=n-pos; if(inw+q*(q-1)/2<l_inwersji)return 0; } //koniec opt for(int i=drz_s ; i<drz_s+n; i++){ if(drzewo[i]==0){ zmien(i,1,drzewo); int akt_inw=inw; akt_inw+=i-drz_s-mniejszeniz(i,drzewo); int zwr=znajdz(pos+1,up_sumk+sumk,akt_inw,n,k,drzewo,drz_s); if(zwr==-1){ drzewo[pos]=i-drz_s+1; return -1; } sumk+=zwr; zmien(i,-1,drzewo); } } return sumk; } int main(){ int drzewo[524290]={},n,d_s=1; long long k; scanf("%d%lld",&n,&k); if( (n*(n-1)/2) %2 == 1 ){ printf("NIE"); return 0; } l_inwersji=n*(n-1)/4; while(d_s<n){ d_s=d_s<<1; } if(znajdz(0,0,0,n,k,drzewo,d_s)==-1){ printf("TAK\n"); for(int i=0;i<n;i++){ printf("%d ",drzewo[i]); } }else{ printf("NIE"); } return 0; } |
English