結果
問題 | No.318 学学学学学 |
ユーザー |
![]() |
提出日時 | 2019-02-08 14:34:44 |
言語 | C (gcc 13.3.0) |
結果 |
AC
|
実行時間 | 81 ms / 2,000 ms |
コード長 | 8,584 bytes |
コンパイル時間 | 1,258 ms |
コンパイル使用メモリ | 33,280 KB |
実行使用メモリ | 7,220 KB |
最終ジャッジ日時 | 2024-06-22 18:47:37 |
合計ジャッジ時間 | 3,918 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 26 |
ソースコード
#include <float.h>#include <limits.h>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>// 内部定数#define D_ARRAY_MAX 100000 // 最大配列数#define D_SEGT_CNT 131072 // セグメントツリーデータ数(2の累乗)#define D_SEGT_INI 0 // セグメントツリー初期値#define D_TREE_MAX D_ARRAY_MAX // 木の最大データ数#define D_TREE_WCNT 2 // 木の方向数#define D_TREE_LEFT 0 // 木の方向 - 左側#define D_TREE_RIGHT 1 // 木の方向 - 右側// 内部構造体 - 木構造typedef struct Tree {int miVal; // 値int miMin; // 最小位置int miMax; // 最大位置int mi1Height[D_TREE_WCNT]; // 木の高さstruct Tree *mzp1Child[D_TREE_WCNT]; // 子} Tree;// 内部変数static FILE *szpFpI; // 入力static int si1Array[D_ARRAY_MAX]; // 配列static int siACnt; // 配列数static int si1SegT[D_SEGT_CNT * 2]; // セグメントツリーstatic Tree sz1Tree[D_TREE_MAX]; // 木の実データstatic int siTCnt; // 木の実データ数static Tree *szpTop; // 先頭の木データ// セグメントツリー - 更新intfSegTUp(int piUpS // <I> 更新範囲 - 開始 0~, int piUpE // <I> 更新範囲 - 終了 0~, int piUpVal // <I> 更新値, int piSNo // <I> セグメント木の配列番号 1~, int piSCrgS // <I> セグメント木の担当範囲 - 開始 0~, int piSCrgE // <I> セグメント木の担当範囲 - 終了 0~){// 範囲外チェックif (piUpE < piSCrgS || piSCrgE < piUpS) {return 0;}// 範囲内チェックif (piUpS <= piSCrgS && piSCrgE <= piUpE) {si1SegT[piSNo] = piUpVal; // 更新return 0;}// 更新済みの場合、子に展開しておくif (si1SegT[piSNo] != D_SEGT_INI) { // 更新済みsi1SegT[piSNo * 2] = si1SegT[piSNo];si1SegT[piSNo * 2 + 1] = si1SegT[piSNo];si1SegT[piSNo] = D_SEGT_INI; // 自分を初期化}// 範囲の半分int liHalf = (piSCrgE - piSCrgS + 1) / 2;// 両側の子へfSegTUp(piUpS, piUpE, piUpVal, piSNo * 2, piSCrgS, piSCrgS + liHalf - 1);fSegTUp(piUpS, piUpE, piUpVal, piSNo * 2 + 1, piSCrgE - liHalf + 1, piSCrgE);return 0;}// セグメントツリー - 取得intfSegTGet(int piSNo // <I> セグメント木の配列番号 1~){int liRet;// 初期値liRet = si1SegT[piSNo];// 親に値があれば更新while (piSNo > 1) {piSNo /= 2; // 上位へif (si1SegT[piSNo] != D_SEGT_INI) { // 更新済みliRet = si1SegT[piSNo];}}return liRet;}// 木データ - 作成Tree *fTreeMake(int piVal // <I> 値, int piNo // <I> 位置){// 対象の木データTree *lzpTree = &(sz1Tree[siTCnt]);siTCnt++;// データセットmemset(lzpTree, 0, sizeof(Tree)); // 初期化lzpTree->miVal = piVal; // 値lzpTree->miMin = piNo; // 最小位置lzpTree->miMax = piNo; // 最大位置return lzpTree;}// 木データ - 比較 - 値昇順intfTreeCmp(Tree *pzpTree // <I> 木データ, int piVal // <I> 値){// 値昇順if (piVal < pzpTree->miVal) { // 左側return -1;}else if (piVal > pzpTree->miVal) { // 右側return 1;}return 0;}// 木データ - 高さ取得intfTreeGetHeight(Tree *pzpTree // <I> 対象の木情報){// データ有無if (pzpTree == NULL) {return 0;}if (pzpTree->mi1Height[D_TREE_LEFT] >= pzpTree->mi1Height[D_TREE_RIGHT]) {return pzpTree->mi1Height[D_TREE_LEFT] + 1;}else {return pzpTree->mi1Height[D_TREE_RIGHT] + 1;}}// 木データ - 右回転(親は子の右下へ・子は親の左上へ)intfTreeRttR(Tree **pzppTree // <I> 回転対象){// 現在の子Tree *lzpChild = (*pzppTree)->mzp1Child[D_TREE_LEFT];// 右回転(*pzppTree)->mzp1Child[D_TREE_LEFT] = lzpChild->mzp1Child[D_TREE_RIGHT]; // 親の左側 = 子の右側(*pzppTree)->mi1Height[D_TREE_LEFT] = lzpChild->mi1Height[D_TREE_RIGHT]; // 親の高さ(左) = 子の高さ(右)lzpChild->mzp1Child[D_TREE_RIGHT] = *pzppTree; // 子の右側 = 親lzpChild->mi1Height[D_TREE_RIGHT] = fTreeGetHeight(*pzppTree); // 子の高さ(右) - 親の高さ*pzppTree = lzpChild; // 親 = 子return 0;}// 木データ - 左回転(親は子の左下へ・子は親の右上へ)intfTreeRttL(Tree **pzppTree // <I> 回転対象){// 現在の子Tree *lzpChild = (*pzppTree)->mzp1Child[D_TREE_RIGHT];// 左回転(*pzppTree)->mzp1Child[D_TREE_RIGHT] = lzpChild->mzp1Child[D_TREE_LEFT]; // 親の右側 = 子の左側(*pzppTree)->mi1Height[D_TREE_RIGHT] = lzpChild->mi1Height[D_TREE_LEFT]; // 親の高さ(右) = 子の高さ(左)lzpChild->mzp1Child[D_TREE_LEFT] = *pzppTree; // 子の左側 = 親lzpChild->mi1Height[D_TREE_LEFT] = fTreeGetHeight(*pzppTree); // 子の高さ(左) - 親の高さ*pzppTree = lzpChild; // 親 = 子return 0;}// 木データ - 追加・削除の共通処理// 戻り値:[1]高さの変更あり [0]高さの変更なしintfTreeComAddDel(Tree **pzppNow // <I> 現在の木情報, int piWay // <I> 対象の方向){// 高さの変更があるかチェックint liNew = fTreeGetHeight((*pzppNow)->mzp1Child[piWay]);if ((*pzppNow)->mi1Height[piWay] == liNew) { // 変化なしreturn 0;}(*pzppNow)->mi1Height[piWay] = liNew; // 更新// 高さが離れている場合、回転if ((*pzppNow)->mi1Height[D_TREE_LEFT] - (*pzppNow)->mi1Height[D_TREE_RIGHT] > 1) { // 左側が高いfTreeRttR(pzppNow); // 右回転}else if ((*pzppNow)->mi1Height[D_TREE_RIGHT] - (*pzppNow)->mi1Height[D_TREE_LEFT] > 1) { // 右側が高いfTreeRttL(pzppNow); // 左回転}return 1;}// 木データ - 追加// 戻り値:[1]高さの変更あり [0]高さの変更なし [-1]追加なしintfTreeAdd(Tree **pzppNow // <I> 現在の木情報, int piVal // <I> 値, int piNo // <I> 位置){// 作成if (*pzppNow == NULL) {*pzppNow = fTreeMake(piVal, piNo);return 1;}// 比較int liRet = fTreeCmp(*pzppNow, piVal);// 一致if (liRet == 0) {(*pzppNow)->miMax = piNo; // 最大位置 - 更新return -1;}// 方向の判別int liWay;if (liRet < 0) { // 左側liWay = D_TREE_LEFT;}else { // 右側liWay = D_TREE_RIGHT;}// 下位へliRet = fTreeAdd(&((*pzppNow)->mzp1Child[liWay]), piVal, piNo);if (liRet < 1) { // 高さの変更なし or 追加なしreturn liRet;}// 追加・削除の共通処理return fTreeComAddDel(pzppNow, liWay);}// 木データ - 全データのループintfTreeAll(Tree *pzpNow // <I> 現在の木情報){// データ有無if (pzpNow == NULL) {return 0;}// 左側fTreeAll(pzpNow->mzp1Child[D_TREE_LEFT]);// セグメントツリー - 更新fSegTUp(pzpNow->miMin, pzpNow->miMax, pzpNow->miVal, 1, 0, D_SEGT_CNT - 1);// 右側fTreeAll(pzpNow->mzp1Child[D_TREE_RIGHT]);return 0;}// 実行メインintfMain(int piTNo // <I> テスト番号 1~){int i;char lc1Buf[1024];// データ - 初期化memset(si1SegT, 0, sizeof(si1SegT)); // セグメントツリーsiTCnt = 0; // 木の実データ数szpTop = NULL; // 先頭の木データ// 入力 - セット#ifdef D_TESTsprintf(lc1Buf, ".\\Test\\T%d.txt", piTNo);szpFpI = fopen(lc1Buf, "r");#elseszpFpI = stdin;#endif// 配列数 - 取得fgets(lc1Buf, sizeof(lc1Buf), szpFpI);sscanf(lc1Buf, "%d", &siACnt);// 配列 - 取得for (i = 0; i < siACnt; i++) {int liVal;fscanf(szpFpI, "%d", &liVal);// 木 - 追加fTreeAdd(&szpTop, liVal, i);}fgets(lc1Buf, sizeof(lc1Buf), szpFpI);// 木の数でループfTreeAll(szpTop);// セグメントツリー - 取得for (i = 0; i < siACnt; i++) {si1Array[i] = fSegTGet(D_SEGT_CNT + i);}// 結果 - 1つ目printf("%d", si1Array[0]);// 結果 - 2つ目以降for (i = 1; i < siACnt; i++) {printf(" %d", si1Array[i]);}// 改行printf("\n");// テストファイルクローズ#ifdef D_TESTfclose(szpFpI);#endifreturn 0;}intmain(){#ifdef D_TESTint i;for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {fMain(i);}#elsefMain(0);#endifreturn 0;}