Submission #434197

#TimeUsernameProblemLanguageResultExecution timeMemory
434197Tiago_MarquesWerewolf (IOI18_werewolf)C++17
49 / 100
784 ms62140 KiB
#include "werewolf.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;

#define REP(i, a, b) for (ll i=a; i<b; i++)
#define pb push_back

int ordem[200000];
vector<int> graph[200000];
int sparse_maximo[200000][20];
int sparse_minimo[200000][20];
int posicao[200000];
int visited[200000] = {};
queue<int> possiveis[2];

void dfs (int u, int indice, int type, int r, int l)
{
    visited[u] = indice + 1;
    for (auto v: graph[u])
    {
        if (visited[v] > indice)
            continue;
        if ((type == 0 && v >= l) || (type == 1 && v <= r && v >= l) || (type == 2 && v <= r))
        {
            if (type != 2)
                possiveis[type].push (v);
            dfs (v, indice, type, r, l);
        }
    }
}

void create (int N)
{
    for (ll i=N-1; i>=0; i--)
    {
        sparse_maximo[i][0] = ordem[i];
        sparse_minimo[i][0] = ordem[i];
        REP(j, 1, 20)
        {
            if (i + (1<<j) > N)
                break;
            sparse_maximo[i][j] = max (sparse_maximo[i][j-1], sparse_maximo[i + (1<<(j-1))][j-1]);
            sparse_minimo[i][j] = min (sparse_minimo[i][j-1], sparse_minimo[i + (1<<(j-1))][j-1]);
        }
    }
}

int maximizar (int a, int b)
{
    int i = log2(b - a + 1);
    return max (sparse_maximo[a][i], sparse_maximo[b - (1<<i) + 1][i]);
}

int minimizar (int a, int b)
{
    int i = log2(b - a + 1);
    return min (sparse_minimo[a][i], sparse_minimo[b - (1<<i) + 1][i]);
}

std::vector<int> check_validity(int N, std::vector<int> X, std::vector<int> Y, std::vector<int> S, std::vector<int> E, std::vector<int> L, std::vector<int> R)
{
    if (N <= 3000 && (int)X.size() <= 6000 && (int)S.size() <= 3000)
    {
        int Q = S.size();
        int M = X.size();
        REP(i, 0, M)
        {
            graph[X[i]].pb (Y[i]);
            graph[Y[i]].pb (X[i]);
        }
        vector<int> ans(Q, 0);
        REP(i, 0, Q)
        {
            if (S[i] < L[i] || E[i] > R[i])
            {
                ans[i] = 0;
                continue;
            }
            possiveis[0].push (S[i]);
            dfs (S[i], i, 0, R[i], L[i]);
            while (!possiveis[0].empty())
            {
                dfs (possiveis[0].front(), i, 1, R[i], L[i]);
                if (possiveis[0].front() <= R[i] && possiveis[0].front() >= L[i])
                    possiveis[1].push (possiveis[0].front());
                possiveis[0].pop();
                if (visited[E[i]] > i)
                {
                    ans[i] = 1;
                    while (!possiveis[0].empty())
                        possiveis[0].pop();
                    while (!possiveis[1].empty())
                        possiveis[1].pop();
                    break;
                }
            }
            if (ans[i] != 0)
                continue;
            while (!possiveis[1].empty())
            {
                dfs (possiveis[1].front(), i, 2, R[i], L[i]);
                possiveis[1].pop();
                if (visited[E[i]] > i)
                {
                    ans[i] = 1;
                    while (!possiveis[1].empty())
                        possiveis[1].pop();
                    break;
                }
            }
        }
        return ans;
    }
    int Q = S.size();
    vector<int> ans(Q);
    REP(i, 0, (int)X.size())
    {
        graph[X[i]].pb (Y[i]);
        graph[Y[i]].pb (X[i]);
    }
    REP(i, 0, N)
    {
        if ((int)graph[i].size() == 1)
        {
            ordem[0] = i;
            posicao[i] = 0;
            break;
        }
    }
    ordem[1] = graph[ordem[0]][0];
    posicao[ordem[1]] = 1;
    REP(i, 2, N)
    {
        if (graph[ordem[i-1]][0] == ordem[i-2])
            ordem[i] = graph[ordem[i-1]][1];
        else
            ordem[i] = graph[ordem[i-1]][0];
        posicao[ordem[i]] = i;
    }
    create(N);
    REP(i, 0, Q)
    {
        int inicio = posicao[S[i]];
        int fim = posicao[E[i]];
        if (S[i] < L[i] || E[i] > R[i])
        {
            ans[i] = 0;
            continue;
        }
        if (inicio < fim)
        {
            int minimo = inicio, maximo = fim;
            while (minimo != maximo)
            {
                int med = (minimo + maximo + 1)/2;
                if (minimizar(inicio, med) < L[i])
                    maximo = med - 1;
                else
                    minimo = med;
            }
            if (maximizar(minimo, fim) > R[i])
                ans[i] = 0;
            else
                ans[i] = 1;
        }
        else
        {
            int minimo = fim, maximo = inicio;
            while (minimo != maximo)
            {
                int med = (minimo + maximo)/2;
                if (minimizar(med, inicio) < L[i])
                    minimo = med + 1;
                else
                    maximo = med;
            }
            if (maximizar(fim, minimo) > R[i])
                ans[i] = 0;
            else
                ans[i] = 1;
        }
    }
    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...