답안 #633425

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
633425 2022-08-22T12:48:43 Z JeanBombeur 송신탑 (IOI22_towers) C++17
0 / 100
429 ms 18612 KB
#include "towers.h"
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;

//  <|°_°|>

//  M. Broccoli

//  The hardest choices require the strongest wills

//  What is better - to be born good, or to overcome your evil nature with great effort ?

const int MAX_TOWERS = (1e5);
const int LOG = (17);
const int SIZE = (1 << LOG);

struct node {
    int left, right, sum;
};

vector <pair <int, int>> Root;

vector <node> Tree;

int TreeMax[2 * MAX_TOWERS];
int TreeMin[2 * MAX_TOWERS];

pair <int, int> Valleys[MAX_TOWERS];

int nbTowers;

int Copy(int a, int &b) {
    Tree.push_back(Tree[a]);
    return b = Tree.size() - 1;
}

int MakeRoot(int a = 1) {
    Root.push_back({0, Copy(Root.back().second, a)});
    return Root.back().second;
}

void Remove(int node, int target, int left = 0, int right = SIZE) {
    Tree[node].sum --;
    if (right - left == 1)
        return;
    int mid = (left + right) >> 1;
    if (target < mid)
        Remove(Copy(Tree[node].left, Tree[node].left), target, left, mid);
    else
        Remove(Copy(Tree[node].right, Tree[node].right), target, mid, right);
    return;
}

int GetSum(int node, int qleft, int qright, int left = 0, int right = SIZE) {
    if (left >= qright || right <= qleft)
        return 0;
    if (qleft <= left && right <= qright)
        return Tree[node].sum;
    int mid = (left + right) >> 1;
    return GetSum(Tree[node].left, qleft, qright, left, mid) + GetSum(Tree[node].right, qleft, qright, mid, right);
}

int GetPrev(int node, int target, int left = 0, int right = SIZE) {
    if (!Tree[node].sum)
        return -1;
    if (right - left == 1)
        return left;
    int mid = (left + right) >> 1;
    int ans = -1;
    if (target > mid)
        ans = GetPrev(Tree[node].right, target, mid, right);
    return ans < 0 ? GetPrev(Tree[node].left, target, left, mid) : ans;
}

int GetNext(int node, int target, int left = 0, int right = SIZE) {
    if (!Tree[node].sum)
        return -1;
    if (right - left == 1)
        return left;
    int mid = (left + right) >> 1;
    int ans = -1;
    if (target + 1 < mid)
        ans = GetNext(Tree[node].left, target, left, mid);
    return ans < 0 ? GetNext(Tree[node].right, target, mid, right) : ans;
}

int GetMax(int left, int right) {
    int ans = 0;
    for (left += nbTowers, right += nbTowers; left < right; left >>= 1, right >>= 1)
    {
        if (left & 1)
            ans = max(ans, TreeMax[left ++]);
        if (right & 1)
            ans = max(ans, TreeMax[-- right]);
    }
    return ans;
}

int Mini(int a, int b) {
    return TreeMax[a + nbTowers] < TreeMax[b + nbTowers] ? a : b;
}

int GetMin(int left, int right) {
    int ans = left;
    for (left += nbTowers, right += nbTowers; left < right; left >>= 1, right >>= 1)
    {
        if (left & 1)
            ans = Mini(ans, TreeMin[left ++]);
        if (right & 1)
            ans = Mini(ans, TreeMin[-- right]);
    }
    return ans;
}

void init(int N, vector <int> H) {
    nbTowers = N;
    Tree.resize(2 * SIZE, {-1, -1, 0});
    int cnt = 0;
    for (int i = 0; i < nbTowers; i ++)
    {
        TreeMax[i + nbTowers] = H[i];
        TreeMin[i + nbTowers] = i;
        if ((!i || H[i] < H[i - 1]) && (i + 1 == nbTowers || H[i] < H[i + 1]))
        {
            Tree[i + SIZE].sum = 1;
            Valleys[cnt ++] = {H[i], i};
        }
    }
    for (int i = SIZE - 1; i; i --)
    {
        Tree[i] = {2 * i, 2 * i + 1, Tree[2 * i].sum + Tree[2 * i + 1].sum};
    }
    for (int i = nbTowers - 1; i; i --)
    {
        TreeMax[i] = max(TreeMax[2 * i], TreeMax[2 * i + 1]);
        TreeMin[i] = Mini(TreeMin[2 * i], TreeMin[2 * i + 1]);
    }
    Root.push_back({0, 1});
    sort(Valleys, Valleys + cnt);
    for (int i = cnt - 1; i; i --)
    {
        int id = Valleys[i].second;
        int root = MakeRoot();
        Remove(root, id);
        int left = GetPrev(root, id);
        int right = GetNext(root, id);
        left = left < 0 ? 1 << 30 : GetMax(left, id);
        right = right < 0 ? 1 << 30 : GetMax(id, right);
        Root.back().first = min(left, right) - TreeMax[id + nbTowers];
    }
    return;
}

int max_towers(int left, int right, int delta) {
    int root = 0;
    int sz = Root.size();
    for (int jump = SIZE; jump; jump >>= 1)
    {
        if (jump + root < sz && delta > Root[jump + root].first)
            root += jump;
    }
    root = Root[root].second;
    int ans = GetSum(root, left, ++ right);
    if (!ans)
        return 1;
    int next = GetNext(root, left - 1), prev = GetPrev(root, right);
    left = GetMin(left, next), right = GetMin(prev, right);
    ans += GetMax(left, next) - delta >= max(TreeMax[left + nbTowers], TreeMax[next + nbTowers]);
    ans += GetMax(prev, right) - delta >= max(TreeMax[prev + nbTowers], TreeMax[right - nbTowers]);
    return ans;
}
# 결과 실행 시간 메모리 Grader output
1 Incorrect 429 ms 7848 KB 12th lines differ - on the 1st token, expected: '2', found: '1'
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 6480 KB 1st lines differ - on the 1st token, expected: '13', found: '15'
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 6480 KB 1st lines differ - on the 1st token, expected: '13', found: '15'
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 36 ms 18612 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 306 ms 6992 KB 1st lines differ - on the 1st token, expected: '7197', found: '5956'
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 6480 KB 1st lines differ - on the 1st token, expected: '13', found: '15'
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 429 ms 7848 KB 12th lines differ - on the 1st token, expected: '2', found: '1'
2 Halted 0 ms 0 KB -