이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
struct Requete {
int noeudDep, noeudArrivee, borneMin, borneMax; //Données de l'entrée
//noeudDep c'est humain noeudArrivee c'est loup-garou
int iReq;
int noeudPlus, noeudMoins;
bool possible;
bool operator < (const Requete &autre) const
{
return iReq < autre.iReq;
}
};
const int BORNE = 2e5 + 1, BCP = ceil(log2(BORNE)), TREE = (1 << (BCP + 1));
vector<int> voisins[BORNE];
vector<int> enfantsPlus[BORNE], enfantsMoins[BORNE];
int dsu_ens[BORNE];
int profondeurPlus[BORNE], profondeurMoins[BORNE];
vector<int> ancetresPlus[BORNE], ancetresMoins[BORNE];
int ancetresDfs[BORNE];
set<int> eulerTree;
int debPlus[BORNE], finPlus[BORNE], debMoins[BORNE], finMoins[BORNE];
vector<Requete> requetes[BORNE];
vector<Requete> sac;
int nNoeuds, nArcs, nReqs;
int dsu_find(int iNoeud){
if (dsu_ens[iNoeud] == iNoeud)
return iNoeud;
dsu_ens[iNoeud] = dsu_find(dsu_ens[iNoeud]);
return dsu_ens[iNoeud];
}
void dsu_union(int noeudPere, int noeudEnfant, bool estPlus){
noeudPere = dsu_find(noeudPere), noeudEnfant = dsu_find(noeudEnfant);
dsu_ens[noeudEnfant] = dsu_ens[noeudPere];
if (estPlus)
enfantsPlus[noeudPere].push_back(noeudEnfant);
else
enfantsMoins[noeudPere].push_back(noeudEnfant);
}
void faireDsu(){
for (int iNoeud = 0; iNoeud < nNoeuds; ++iNoeud)
dsu_ens[iNoeud] = iNoeud;
//Le DSU plus : les trucs au-dessus.
for (int iNoeud = nNoeuds - 1; iNoeud >= 0; --iNoeud){
for (int voisin : voisins[iNoeud]){
if (voisin > iNoeud)
dsu_union(iNoeud, voisin, true);
}
}
for (int iNoeud = 0; iNoeud < nNoeuds; ++iNoeud)
dsu_ens[iNoeud] = iNoeud;
for (int iNoeud = 0; iNoeud < nNoeuds; ++iNoeud){
for (int voisin : voisins[iNoeud]){
if (voisin < iNoeud)
dsu_union(iNoeud, voisin, false);
}
}
}
void buildBinaryPlus(int iNoeud, int profCur){
profondeurPlus[iNoeud] = profCur;
ancetresDfs[profCur] = iNoeud;
for (int delta = 1; profCur >= delta; delta *= 2)
ancetresPlus[iNoeud].push_back(ancetresDfs[profCur - delta]);
for (int enfant : enfantsPlus[iNoeud])
buildBinaryPlus(enfant, profCur + 1);
}
void buildBinaryMoins(int iNoeud, int profCur){
profondeurMoins[iNoeud] = profCur;
ancetresDfs[profCur] = iNoeud;
for (int delta = 1; profCur >= delta; delta *= 2)
ancetresMoins[iNoeud].push_back(ancetresDfs[profCur - delta]);
for (int enfant : enfantsMoins[iNoeud])
buildBinaryMoins(enfant, profCur + 1);
}
int trouveRacinePlus(int noeudDep, int borneMax){
//Sorte de dichotomie sur l'arbre.
//Un père est supérieur à ses enfants.
int iAncetre = ancetresPlus[noeudDep].size() - 1;
for (;iAncetre >= 0;--iAncetre){
if ((int)ancetresPlus[noeudDep].size() > iAncetre){
int noeudTest = ancetresPlus[noeudDep][iAncetre];
if (noeudTest <= borneMax)
noeudDep = noeudTest;
}
}
return noeudDep;
}
int trouveRacineMoins(int noeudDep, int borneMin){
//Ici un père est inférieur à ses enfants.
int iAncetre = ancetresMoins[noeudDep].size() - 1;
for (; iAncetre >= 0; --iAncetre){
if ((int)ancetresMoins[noeudDep].size() > iAncetre){
int noeudTest = ancetresMoins[noeudDep][iAncetre];
if (noeudTest >= borneMin)
noeudDep = noeudTest;
}
}
return noeudDep;
}
int temps = 0;
void tourEulerienPlus(int iNoeud){
debPlus[iNoeud] = temps++;
for (int enfant : enfantsPlus[iNoeud])
tourEulerienPlus(enfant);
finPlus[iNoeud] = temps++;
}
bool reqTree(int gauche, int droite){
auto it = eulerTree.lower_bound(gauche);
if (it != eulerTree.end() && *it <= droite)
return true;
return false;
}
void makeDfs(int iNoeud){
for (int enfant : enfantsMoins[iNoeud])
makeDfs(enfant);
eulerTree.insert(debPlus[iNoeud]);
for (Requete requete : requetes[iNoeud]){
requete.possible = reqTree(debPlus[iNoeud], finPlus[iNoeud]);
}
}
void updReq(){
for (Requete& req : sac){
req.noeudPlus = trouveRacinePlus(req.noeudArrivee, req.borneMax);
req.noeudMoins = trouveRacineMoins(req.noeudDep, req.borneMin);
requetes[req.noeudMoins].push_back(req);
}
}
vector<int> resoud(){
faireDsu();
buildBinaryMoins(0, 0); //La racine de moins est 0
buildBinaryPlus(nNoeuds - 1, 0);
updReq();
tourEulerienPlus(nNoeuds - 1);
makeDfs(0);
vector<int> answers;
vector<Requete> solReq;
for (int iNoeud = 0; iNoeud < nNoeuds; ++iNoeud){
for (Requete req : requetes[iNoeud])
solReq.push_back(req);
}
sort(solReq.begin(), solReq.end());
for (Requete req : solReq)
answers.push_back(req.possible);
return answers;
}
vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R){
nNoeuds = N;
nArcs = X.size();
for (int iArc = 0; iArc < nArcs; ++iArc){
voisins[X[iArc]].push_back(Y[iArc]);
voisins[Y[iArc]].push_back(X[iArc]);
}
nReqs = S.size();
for (int iReq = 0; iReq < nReqs; ++iReq){
int i = iReq;
Requete reqCur= {S[i], E[i], L[i], R[i], iReq, -1, -1, false};
sac.push_back(reqCur);
}
return resoud();
}
컴파일 시 표준 에러 (stderr) 메시지
werewolf.cpp: In function 'void makeDfs(int)':
werewolf.cpp:132:15: warning: variable 'requete' set but not used [-Wunused-but-set-variable]
for (Requete requete : requetes[iNoeud]){
^~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |