답안 #198419

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
198419 2020-01-26T02:25:35 Z model_code Traffickers (RMI18_traffickers) C++14
60 / 100
3500 ms 289056 KB
//  Author: Ștefan Constantin-Buliga
#include <fstream>
#include <cmath>
#include <vector>
#include <string>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <bitset>
#include <cassert>
#include <ctime>
#include <cstdlib>
#include <set>
#include <complex>

using namespace std;

const int SIZE = 1 << 10;

int pointer = SIZE;
char buffer[SIZE];

char Advance() {
    if (pointer == SIZE) {
        fread(buffer, 1, SIZE, stdin);
        pointer = 0;
    }
    return buffer[pointer++];
}

int Read() {
    int answer = 0;
    char ch = Advance();
    while (!isdigit(ch))
        ch = Advance();
    while (isdigit(ch)) {
        answer = answer * 10 + ch - '0';
        ch = Advance();
    }
    return answer;
}

const int MAXN = 30000;
const int MAXLOG = 14;
const int MAXD = 20;
const int MAXNODES = 131072;

vector<int> g[1 + MAXN];
int dad[1 + MAXLOG][1 + MAXN], depth[1 + MAXN], first[1 + MAXN], last[1 + MAXN], number = 0;

void DFS(int node, int father) {
    number++;
    first[node] = number;
    dad[0][node] = father;
    depth[node] = depth[father] + 1;
    for (int i = 1; (1 << i) < depth[node]; i++)
        dad[i][node] = dad[i - 1][dad[i - 1][node]];
    for (auto &son : g[node])
        if (son != father)
            DFS(son, node);
    number++;
    last[node] = number;
}

int Raise(int node, int delta) {
    if (delta < 0)
        return 0;
    for (int i = 0; i <= MAXLOG; i++)
        if (delta & (1 << i))
            node = dad[i][node];
    return node;
}

int Lca(int a, int b) {
    if (depth[a] < depth[b])
        swap(a, b);
    a = Raise(a, depth[a] - depth[b]);
    if (a == b)
        return a;
    for (int i = MAXLOG; i >= 0; i--)
        if (dad[i][a] != dad[i][b]) {
            a = dad[i][a];
            b = dad[i][b];
        }
    return dad[0][a];
}

struct Treap {
    int value;
    int priority;
    int add;
    int sum;
    Treap *left, *right;

    Treap() {
        value = 0;
        add = 0;
        sum = 0;
        priority = -1;
        left = right = NULL;
    }

    Treap(int _value, int _priority, int _add, Treap *_left, Treap *_right) {
        value = _value;
        priority = _priority;
        add = _add;
        left = _left;
        right = _right;
        Update();
    }

    void Update() {
        sum = left->sum + right->sum + add;
    }
};

Treap *nil, *tree[1 + MAXD][1 + MAXNODES];

pair<Treap*, Treap*> Split(Treap *node, int value) {
    if (node == nil)
        return make_pair(nil, nil);
    if (node->value <= value) {
        pair<Treap*, Treap*> temp = Split(node->right, value);
        node->right = temp.first;
        node->Update();
        return make_pair(node, temp.second);
    }
    else {
        pair<Treap*, Treap*> temp = Split(node->left, value);
        node->left = temp.second;
        node->Update();
        return make_pair(temp.first, node);
    }
}

Treap* Join(Treap *left, Treap *right) {
    if (left == nil)
        return right;
    if (right == nil)
        return left;
    if (left->priority > right->priority) {
        left->right = Join(left->right, right);
        left->Update();
        return left;
    }
    else {
        right->left = Join(left, right->left);
        right->Update();
        return right;
    }
}

void Initialize() {
    for (int i = 1; i <= MAXD; i++)
        for (int j = 1; j <= MAXNODES; j++)
            tree[i][j] = nil;
}

bool Find(Treap *node, int value) {
    if (node == nil)
        return false;
    if (node->value == value)
        return true;
    if (value < node->value)
        return Find(node->left, value);
    else
        return Find(node->right, value);
}

Treap* Insert(Treap *node, int value, int priority, int add) {
    if (priority < node->priority) {
        if (value < node->value)
            node->left = Insert(node->left, value, priority, add);
        else
            node->right = Insert(node->right, value, priority, add);
        node->Update();
        return node;
    }
    pair<Treap*, Treap*> temp = Split(node, value);
    return new Treap(value, priority, add, temp.first, temp.second);
}

Treap *Erase(Treap *node, int value, int add) {
    if (node->value == value) {
        node->add += add;
        node->Update();
        if (node->add == 0)
            node = Join(node->left, node->right);
        return node;
    }
    if (value < node->value)
        node->left = Erase(node->left, value, add);
    else
        node->right = Erase(node->right, value, add);
    node->Update();
    return node;
}

void Update(int id, int node, int left, int right, int where, int t, int add) {
    if (!Find(tree[id][node], t))
        tree[id][node] = Insert(tree[id][node], t, rand(), add);
    else
        tree[id][node] = Erase(tree[id][node], t, add);
    if (left == right)
        return;
    int middle = (left + right) / 2;
    if (where <= middle)
        Update(id, 2 * node, left, middle, where, t, add);
    else
        Update(id, 2 * node + 1, middle + 1, right, where, t, add);
}

void AddTraficker(int a, int b, int add) {
    int c = Lca(a, b), d = depth[a] - depth[c] + depth[b] - depth[c] + 1;
    for (int node = a, t = 0; node != c; node = dad[0][node], t++) {
        Update(d, 1, 1, number, first[node], t, add);
        Update(d, 1, 1, number, last[node], t, -add);
    }
    Update(d, 1, 1, number, first[c], depth[a] - depth[c], add);
    Update(d, 1, 1, number, last[c], depth[a] - depth[c], -add);
    for (int node = b, t = d - 1; node != c; node = dad[0][node], t--) {
        Update(d, 1, 1, number, first[node], t, add);
        Update(d, 1, 1, number, last[node], t, -add);
    }
}

int Query(int id, int node, int left, int right, int from, int to, int x, int y) {
    if (from <= left && right <= to) {
        pair<Treap*, Treap*> first = Split(tree[id][node], x - 1), second = Split(first.second, y);
        int answer = second.first->sum;
        tree[id][node] = Join(first.first, Join(second.first, second.second));
        return answer;
    }
    int answer = 0, middle = (left + right) / 2;
    if (from <= middle)
        answer += Query(id, 2 * node, left, middle, from,  to, x, y);
    if (middle + 1 <= to)
        answer += Query(id, 2 * node + 1, middle + 1, right, from, to, x, y);
    return answer;
}

int Get(int a, int b, int c, int d, int temp, int x, int y) {
    int answer = 0;
    answer += Query(d, 1, 1, number, first[c], first[a], x, y);
    if (temp)
        answer += Query(d, 1, 1, number, first[temp], first[b], x, y);
    return answer;
}

long long GetAnswer(int a, int b, int x, int y) {
    int c = Lca(a, b), temp = Raise(b, depth[b] - depth[c] - 1);
    long long answer = 0;
    for (int d = 1; d <= MAXD; d++) {
        if (y - x + 1 <= d && x % d <= y % d) {
            answer += Get(a, b, c, d, temp, x % d, y % d);
            continue;
        }
        int x0 = x - x % d + d - 1, y0 = y - y % d;
        answer += Get(a, b, c, d, temp, x % d, d - 1) + Get(a, b, c, d, temp, 0, y % d);
        if (x0 + 1 <= y0 - 1)
            answer += 1LL * ((y0 - x0 - 1) / d) * Get(a, b, c, d, temp, 0, d - 1);
    }
    return answer;
}

int main() {
    //freopen("tema.in", "r", stdin);
    //freopen("tema.out", "w", stdout);
    nil = new Treap();
    nil->left = nil->right = nil;
    int n = Read();
    for (int i = 1; i < n; i++) {
        int a = Read(), b = Read();
        g[a].push_back(b);
        g[b].push_back(a);
    }
    DFS(1, 0);
    Initialize();
    int k = Read();
    for (int i = 1; i <= k; i++) {
        int a = Read(), b = Read();
        AddTraficker(a, b, 1);
    }
    int q = Read();
    for (int i = 1; i <= q; i++) {
        int type = Read();
        if (type != 3) {
            int a = Read(), b = Read();
            if (type == 1)
                AddTraficker(a, b, 1);
            else
                AddTraficker(a, b, -1);
        }
        else {
            int a = Read(), b = Read(), x = Read(), y = Read();
            printf("%lld\n", GetAnswer(a, b, x, y));
        }
    }
    return 0;
}

Compilation message

traffickers.cpp: In function 'char Advance()':
traffickers.cpp:26:14: warning: ignoring return value of 'size_t fread(void*, size_t, size_t, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
         fread(buffer, 1, SIZE, stdin);
         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 21880 KB Output is correct
2 Correct 46 ms 25720 KB Output is correct
3 Correct 46 ms 25720 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 970 ms 62840 KB Output is correct
2 Correct 1029 ms 61120 KB Output is correct
3 Correct 871 ms 62156 KB Output is correct
4 Correct 972 ms 63480 KB Output is correct
5 Correct 1006 ms 62328 KB Output is correct
6 Correct 990 ms 62380 KB Output is correct
7 Correct 980 ms 62712 KB Output is correct
8 Correct 927 ms 63096 KB Output is correct
9 Correct 896 ms 63480 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 3597 ms 280344 KB Time limit exceeded
2 Execution timed out 3612 ms 284152 KB Time limit exceeded
3 Execution timed out 3592 ms 286588 KB Time limit exceeded
4 Execution timed out 3594 ms 261460 KB Time limit exceeded
5 Execution timed out 3590 ms 192120 KB Time limit exceeded
6 Execution timed out 3590 ms 286232 KB Time limit exceeded
7 Execution timed out 3593 ms 289056 KB Time limit exceeded
8 Execution timed out 3597 ms 288676 KB Time limit exceeded