Дерево - это простой граф, в котором каждые две вершины соединены ровно одним путем. Вам дано корневое дерево с вершинами, и лампа помещается в каждую вершину дерева.
Вам даются запросы следующих двух типов:
1 v: You switch the lamp placed on the vertex v, that is, either from On to Off or Off to On.
2 v: Determine the number of vertices connected to the subtree of v if you only consider the lamps that are in On state. In other words, determine the number of vertices in the subtree of v , such as u, that can reach from v by using only the vertices that have lamps in the On state.
Примечание: изначально все лампы включаются, и дерево основывается на номере вершины.
Формат ввода
Первая строка: два целых числа, обозначающие количество вершин и запросов Следующие строки: два числа и обозначающие ребро между вершинами и Следующими строками: два целых числа и, где - тип запроса. Примечание. Гарантируется, что эти ребра образуют дерево с корнем из вершины.
Формат вывода Для каждого запроса типа 2 выведите ответ в одной строке.
Ограничения
SAMPLE INPUT
5 4
1 2
2 3
1 4
4 5
1 3
2 2
1 3
2 2
SAMPLE OUTPUT
1
2
Пояснение:
Это дерево в первую очередь:
The tree after turning off lamp in node
Obviously the answer now for vertex is
введите описание изображения здесь
Код:
void updateSubSwitches(vector<vector<int>> &tree,vector<int> &parent, vector<int> &switchesSubTree, int vertex, bool flag) {
if(flag) {
switchesSubTree[vertex]=1;
for(int i=0;i<tree[vertex].size();i++) {
switchesSubTree[vertex] += switchesSubTree[tree[vertex][i]];
}
int parentVertex=parent[vertex];
while(switchesSubTree[parentVertex]!=0 && parentVertex!=0) {
switchesSubTree[parentVertex]=switchesSubTree[parentVertex]+switchesSubTree[vertex];
parentVertex=parent[parentVertex];
}
if(parentVertex == 0) {
switchesSubTree[0]=switchesSubTree[0]+switchesSubTree[vertex];
}
} else {
int parentVertex=parent[vertex];
while(switchesSubTree[parentVertex]!=0 && parentVertex!=0) {
switchesSubTree[parentVertex]=switchesSubTree[parentVertex]-switchesSubTree[vertex];
parentVertex=parent[parentVertex];
}
if(parentVertex == 0) {
switchesSubTree[0]=switchesSubTree[0]-switchesSubTree[vertex];
}
switchesSubTree[vertex]=0;
}
}
int initialSubSwitches(vector<vector<int>> &tree, vector<int> &switchesSubTree,int vertex) {
if(switchesSubTree[vertex] == -1) {
if(tree[vertex].size() > 0) {
switchesSubTree[vertex] = 1;
//cout<<vertex<<endl;
for(int i=0;i<tree[vertex].size();i++){
switchesSubTree[vertex] += initialSubSwitches(tree,switchesSubTree,tree[vertex][i]);
}
return switchesSubTree[vertex];
} else {
//cout<<vertex<<endl;
switchesSubTree[vertex] = 1;
return 1;
}
}
}
int main() {
int n,q;
cin>>n>>q;
vector<vector<int>> tree(n);
vector<bool> arr(n,true);
vector<int> switchesSubTree(n,-1);
vector<int> parent(n);
for(int i=1;i<=n-1;i++) {
int a,b;
cin>>a>>b;
tree[a-1].push_back(b-1);
parent[b-1] = a-1;
}
initialSubSwitches(tree,switchesSubTree,0);
for(int i=1;i<=q;i++) {
int b,v;
cin>>b>>v;
if(b==1) {
arr[v-1]=!arr[v-1];
updateSubSwitches(tree,parent,switchesSubTree,v-1,arr[v-1]);
} else {
cout<<switchesSubTree[v-1]<<endl;
}
}
}
Алгоритм:
Инициализация
- дерево хранит график
- arr хранит если лампа в вершине v включена или выключена.
- Switches SubTree хранит количество включенных ламп для этого поддерева.
Шаги:
1. initialize the switchesSubTree array if initially all lamps are ON.
2. For each query,
2.1 if lamp is turned OFF:
decrease its ancestors by switchesSubTree[vertex] until we get a node whose lamp is OFF or we reach root vertex
make switchesSubTree[vertex] = 0
2.2 if lamp is turned ON:
calculate no. of lamps swithced ON for this vertex which is
switchesSubTree[vertex] = 1 + sum(all lamps of children)
increase the lamps for ancestors until we get a node whose lamp is OFF or we reach root vertex.
Но решение дает ПРЕВЫШЕНИЕ ВРЕМЕНИ для некоторых тестовых случаев, а также неверно для некоторых тестовых случаев. В чем я ошибаюсь и что может быть более эффективным и лучшим решением?