답안 #726577

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
726577 2023-04-19T05:51:16 Z MadokaMagicaFan Prize (CEOI22_prize) C
0 / 100
1342 ms 184424 KB
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define N 1000000
#define K 21
typedef long long ll;

int n, req;

typedef struct {
    int a, b;
    ll w;
} edge;

typedef struct{
    int ec;
    edge e[2*N+2];
    int in[N];
} edges;

typedef struct {
    int r;
    int j[N][K];
    int d[N], vis[N];
    ll h[N];
    edges *ne, *se;
} tree;

tree t1, t2;
int nodes[N], nc;
int ei[N], ec;

void
add_edge(edges *e, int a, int b, ll w)
{
    e->e[e->ec++] = (edge){a, b, w};
    e->e[e->ec++] = (edge){b, a, -w};
}

int
_sort_edge(const void *a, const void *b)
{
    return ((edge *)a)->a - ((edge *)b)->a;
}

void
edges_make(edges *e)
{
    int x, y;
    x = y = 0;
    qsort(e->e, e->ec, sizeof *(e->e), _sort_edge);
    while (x < n && y < e->ec) {
        if (x <= e->e[y].a)
            e->in[x++] = y;
        else
            ++y;
    }

    while (x < n)
        e->in[x++] = e->ec;
}

int
_sort_nodes(const void *a, const void *b)
{
    return ei[*(int *)a] - ei[*(int *)b];
}

void
tree_depth_dfs(tree *t, int x, int d)
{
    t->d[x] = d;
    if (t == &t1)
        nodes[nc++] = x;
    ei[x] = ec++;
    for (int i = t->ne->in[x]; i < t->ne->ec && t->ne->e[i].a == x; ++i) {
        if (t->ne->e[i].b == t->j[x][0]) continue;
        tree_depth_dfs(t, t->ne->e[i].b, d+1);
    }
    return;
}

void
tree_init(tree *t, int *p)
{
    int i, k;

    t->ne = malloc(sizeof *t->ne);
    t->se = malloc(sizeof *t->se);
    for (i = 0; i < n; ++i) {
        --p[i]; t->vis[i] = 0;
        if (p[i] == -2) {
            t->r = i;
            t->j[i][0] = i;
        } else {
            t->j[i][0] = p[i];
            add_edge(t->ne, i, p[i], -1);
        }
    }

    for (k = 1; k < K; ++k)
        for (i = 0; i < n; ++i)
            t->j[i][k] = t->j[t->j[i][k-1]][k-1];

    edges_make(t->ne);
    tree_depth_dfs(t, t->r, 0);
}

int
lca(tree *t, int a, int b)
{
    if (t->d[a] < t->d[b]) {
        a = a + b; b = a - b; a = a - b;
    }

    for (int k = K-1; k >= 0; --k) {
        if (t->d[t->j[a][k]] >= t->d[b])
            a = t->j[a][k];
    }

    assert(t->d[a] == t->d[b]);
    if (a == b) return a;
    for (int k = K-1; k >= 0; --k) {
        if (t->j[a][k] != t->j[b][k]) {
            a = t->j[a][k];
            b = t->j[b][k];
        }
    }
    return t->j[a][0];
}

void
con_depth(tree *t, int x, ll d)
{
    if (t->vis[x]) return;
    t->vis[x] = 1;

    t->h[x] = d;
    for (int i = t->se->in[x]; i < t->se->ec && t->se->e[i].a == x; ++i)
        con_depth(t, t->se->e[i].b, d + t->se->e[i].w);
    return;
}

ll ans[100000][2];

int
main(int argc, char *argv[])
{
    int q, t, i, x, y, z ,w, l;
    int p[N];
    scanf("%d %d %d %d\n", &n, &req, &q, &t);

    for (i = 0; i < n; ++i)
        scanf("%d ", &p[i]);
    tree_init(&t1, p);

    for (i = 0; i < n; ++i)
        scanf("%d ", &p[i]);
    ec = 0; tree_init(&t2, p);

    assert(nc == n);
    qsort(nodes, req, sizeof *nodes, _sort_nodes);

    for (i = 0; i < req; ++i)
        printf("%d ", nodes[i]+1);
    puts("");

    for (i = 0; i < req-1; ++i) {
        printf("? %d %d\n", nodes[i]+1, nodes[i+1]+1);
    }
    puts("!"); fflush(stdout);


    for (i = 0; i < req-1; ++i) {
        scanf("%d %d %d %d", &x, &y, &z, &w);
        l = lca(&t1, nodes[i], nodes[i+1]);
        add_edge(t1.se, nodes[i], l, -x);
        add_edge(t1.se, nodes[i+1], l, -y);
        l = lca(&t2, nodes[i], nodes[i+1]);
        add_edge(t2.se, nodes[i], l, -z);
        add_edge(t2.se, nodes[i+1], l, -w);
    }

    edges_make(t1.se);
    edges_make(t2.se);
    con_depth(&t1, nodes[i], 0);
    con_depth(&t2, nodes[i], 0);

    for (l = 0; l < t; ++l) {
        scanf("%d %d", &x, &y); --x; --y;
        ans[l][0] = t1.h[x] + t1.h[y] - 2ll * t1.h[lca(&t1, x, y)];
        ans[l][1] = t2.h[x] + t2.h[y] - 2ll * t2.h[lca(&t2, x, y)];
    }

    assert(0);

    for (l = 0; l < t; ++l) {
        printf("%lld %lld\n", ans[l][0], ans[l][1]);
    }
    fflush(stdout);
}

Compilation message

Main.c: In function 'main':
Main.c:152:5: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  152 |     scanf("%d %d %d %d\n", &n, &req, &q, &t);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.c:155:9: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  155 |         scanf("%d ", &p[i]);
      |         ^~~~~~~~~~~~~~~~~~~
Main.c:159:9: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  159 |         scanf("%d ", &p[i]);
      |         ^~~~~~~~~~~~~~~~~~~
Main.c:176:9: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  176 |         scanf("%d %d %d %d", &x, &y, &z, &w);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.c:191:9: warning: ignoring return value of 'scanf' declared with attribute 'warn_unused_result' [-Wunused-result]
  191 |         scanf("%d %d", &x, &y); --x; --y;
      |         ^~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 632 ms 94240 KB Time limit exceeded (wall clock)
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 598 ms 94244 KB Time limit exceeded (wall clock)
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 648 ms 94176 KB Time limit exceeded (wall clock)
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 1342 ms 184160 KB Time limit exceeded (wall clock)
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 1239 ms 184424 KB Time limit exceeded (wall clock)
2 Halted 0 ms 0 KB -