In this HackerEarth Number Recovery problem solution A positive integer X has been stolen. But luckily, N hints are available, each described by two integers ai and di, meaning that |X - ai| = di. The hints are numbered 1 through N. While some of those hints are helpful, some might be just a lie. Therefore, we are going to investigate the number X under different possible scenarios.

Initially, we neither trust nor distrust any hint. That is, each hint may be either true or false. Then, in each of the Q stages, we will either:

1 id
Entrust the -th hint (1 <= id <= N). That is, from now on, the -th hint must be true, unless declared otherwise in the future.
2 id
Distrust the -th hint (1 <= id <= N). That is, from now on, the -th hint must be false, unless declared otherwise in the future.
3 id
Neutralize the -th hint (1 <= id <= N). That is, from now on, the -th hint may be either true or false, unless declared otherwise in the future.
After each stage, you should determine the number of possible positive values X and report such values in increasing order. If there are infinitely many such values, print -1 instead.


HackerEarth Number Recovery problem solution


HackerEarth Number Recovery problem solution.

#include <stdio.h>
#include <algorithm>
#include <vector>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <queue>
#include <assert.h>
#include <iostream>
using namespace std;

map<int, int> ok;
map<int, int> ban;

queue<int> q;

int main(){
int M, K;
scanf("%d%d", &M, &K);
vector<int> x(M+1), d(M+1);
vector<int> status(M+1, 0);
for(int i=1; i<=M; i++) scanf("%d%d", &x[i], &d[i]);
int entrusted = 0;
for(int i=0; i<K; i++){
int t, id;
scanf("%d%d", &t, &id);
int a = x[id]-d[id], b = x[id]+d[id];
if(status[id] == 1){
ok[a]--;
if(a != b) ok[b]--;
entrusted--;
} else if(status[id] == 2){
ban[a]--;
ban[b]--;
}
status[id] = (t == 3 ? 0 : t);
if(t == 1){
ok[a]++;
if(a != b) ok[b]++;
entrusted++;
q.push(id);
} else if(t == 2){
ban[a]++;
ban[b]++;
}
// get the answer
int idx = -1;
while(!q.empty()){
int x = q.front();
if(status[x] == 1){
idx = x;
break;
}
q.pop();
}
if(idx == -1) printf("-1\n");
else{
int a = x[idx]-d[idx];
int b = x[idx]+d[idx];
vector<int> res;
if(a > 0 && ok[a] == entrusted && ban[a] == 0) res.push_back(a);
if(b > a && ok[b] == entrusted && ban[b] == 0) res.push_back(b);
printf("%d", (int)res.size());
for(int i=0; i<res.size(); i++){
printf(" %d", res[i]);
}
printf("\n");
}
}
return 0;
}

Second solution

#include "bits/stdc++.h"
using namespace std;

map<int,int> bad, good;
multiset<vector<int>> good_pairs;

int main() {
int n, q;
scanf("%d%d", &n, &q);
vector<vector<int>> info(n);
for(int i = 0; i < n; ++i) {
int x, d;
scanf("%d%d", &x, &d);
info[i] = {x - d, x + d};
if(x - d == x + d) {
info[i].pop_back();
}
}
vector<int> state(n);
// bad: -1
// neutral: 0
// trusted: 1
while(q--) {
int type, i;
scanf("%d%d", &type, &i);
--i;
// 1) erase the current state
if(state[i] == -1) {
for(int a : info[i]) {
--bad[a];
}
}
if(state[i] == 1) {
for(int a : info[i]) {
--good[a];
}
good_pairs.erase(good_pairs.find(info[i]));
}
// 2) add a new state
if(type == 1) state[i] = 1;
else if(type == 2) state[i] = -1;
else if(type == 3) state[i] = 0;
else assert(false);
if(state[i] == -1) {
for(int a : info[i]) {
++bad[a];
}
}
if(state[i] == 1) {
for(int a : info[i]) {
++good[a];
}
good_pairs.insert(info[i]);
}
if(good_pairs.empty()) {
puts("-1");
continue;
}
set<int> answer; // set doesn't count twice
for(int a : *good_pairs.begin()) {
if(!bad[a] && a > 0 && good[a] == (int) good_pairs.size()) {
answer.insert(a);
}
}
printf("%d", (int) answer.size());
for(int a : answer) {
printf(" %d", a);
}
puts("");
}
}