In this HackerEarth Completing Subgraphs problem solution There's some unweighted graph with N nodes and M edges. You have to respond to queries of 3 forms:
  1. Given some interval of nodes [l,r] , you need to add edges between every pair of these nodes (even if they are already connected by an edge)
  2. You need to remove all edges added in the ith query of type 1.
  3. Given nodes u and v, you need to print the shortest path from u to v, or say that it doesn't exist.

HackerEarth Completing Subgraphs problem solution


HackerEarth Completing Subgraphs problem solution.

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

#define PB push_back
#define MP make_pair


int n,m,q;
vector<pair<int,double> > adj[1000001];
int nodeptr;

bool useless_vertex[1000001]; //used for queries of type 2

int seencnt = 0;
void construct_segtree_1(int no, int b, int e){ //edges point toward parent
seencnt=max(nodeptr+no,seencnt);
//cout << "LUL " << no << endl;
if(b==e){
adj[b].PB(MP(nodeptr+no,0));
//cout << "from " << b << " to " << nodeptr+no << endl;
}else{
adj[nodeptr+2*no].PB(MP(nodeptr+no,0));
adj[nodeptr+2*no+1].PB(MP(nodeptr+no,0));
//cout << "from " << nodeptr+2*no << " to " <<nodeptr+no << endl;
//cout << "from " << nodeptr+2*no+1 << " to " <<nodeptr+no << endl;
int mid = (b+e)/2;
construct_segtree_1(2*no,b,mid);
construct_segtree_1(2*no+1,mid+1,e);
}
}
void construct_segtree_2(int no, int b, int e){ //edges point toward child
seencnt=max(seencnt,nodeptr+no);
//cout << "HAH " << nodeptr+no << endl;
if(b==e){
adj[nodeptr+no].PB(MP(b,0));
//cout << "from " << nodeptr+no << " to " << b << endl;
}else{
adj[no+nodeptr].PB(MP(nodeptr+2*no,0));
adj[no+nodeptr].PB(MP(nodeptr+2*no+1,0));
//cout << "from " << nodeptr+no << " to " <<nodeptr+2*no << endl;
//cout << "from " << nodeptr+no << " to " <<nodeptr+2*no+1 << endl;
int mid = (b+e)/2;
construct_segtree_2(2*no,b,mid);
construct_segtree_2(2*no+1,mid+1,e);
}
}
int nodeptrold;
int nodeptr2;
void search1(int no, int b, int e, int l, int r, int dummy){
if(b>r || e<l) return;
if(l<=b && e<=r){
//insert edge to dummy
//cout << "ADDED "<<no+nodeptrold << " TO " << dummy << endl;
adj[no+nodeptrold].PB(MP(dummy,.5));
return;
}

int mid = (b+e)/2;
search1(2*no,b,mid,l,r,dummy);
search1(2*no+1,mid+1,e,l,r,dummy);
}
void search2(int no, int b, int e, int l, int r, int dummy){
if(b>r || e<l) return;
if(l<=b && e<=r){
//cout << "ADDED " <<dummy << " TO " << no+nodeptr2 << endl;
adj[dummy].PB(MP(no+nodeptr2,.5));
return;
}
int mid = (b+e)/2;
search2(2*no,b,mid,l,r,dummy);
search2(2*no+1,mid+1,e,l,r,dummy);
}

vector<int> dummyidxs;

bool myvis[1000001];
double dist[1000001];
int main()
{
scanf("%d %d",&n,&m);

for(int i=0; i < m; i++){
int u,v;
scanf("%d %d",&u,&v);
u--; v--;
adj[u].PB(MP(v,1));
adj[v].PB(MP(u,1));
}
nodeptr = n-1;
seencnt=n-1;
construct_segtree_1(1,0,n-1);
nodeptrold=nodeptr;
nodeptr = seencnt;
nodeptr2=nodeptr;
construct_segtree_2(1,0,n-1);


int q;
scanf("%d",&q);
for(int query=0;query<q;query++){
int ty;
scanf("%d",&ty);
if(ty==1){
int l,r;
scanf("%d %d",&l,&r);
l--; r--;
seencnt++;
search1(1,0,n-1,l,r,seencnt);
search2(1,0,n-1,l,r,seencnt);
dummyidxs.PB(seencnt);
}else if(ty==2){
int i;
scanf("%d",&i);
i--;
assert(i<dummyidxs.size());
useless_vertex[dummyidxs[i]]=true;
}else if(ty==3){
//dijkstra
int u,v;
scanf("%d %d",&u,&v);
u--; v--;

priority_queue<pair<double,int>,vector<pair<double,int> >,greater<pair<double,int> > > pq;
pq.push(MP(0,u));
for(int i=0;i<seencnt+1;i++) {
myvis[i]=false;
dist[i] = 100000000;
}
dist[u]=0;
while(!pq.empty()){
pair<double,int> po = pq.top();
pq.pop();
int vert = po.second;
double tdis = po.first;
if(useless_vertex[vert] || myvis[vert] || tdis-dist[vert]>1e-7) continue;
myvis[vert]=true;
for(pair<int,double> adjacent : adj[vert]){
int to = adjacent.first;
double ed = adjacent.second;
if(dist[vert]+ed<dist[to]){
dist[to]=dist[vert]+ed;
if(!myvis[to]) pq.push(MP(dist[to],to));
}
}
}
if(!myvis[v]){
cout << -1 << endl;
}
else cout << int(round(dist[v])) << endl;
}
}



}

Second solution

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

#define ii pair<int, int>
#define ff first
#define ss second
#define N 100005

int n, curr, memo[N], spoilt[10 * N], D[10 * N];;
vector<ii> v[10 * N];
int tree[2][4 * N];

int get(int node, int idx){
if(!idx)
return n + node;
return 5 * n + node;
}

void build_tree(int idx, int node, int l, int r){
if(l == r){
if(!idx)
v[l].push_back(ii(get(node, idx), 0));
else
v[get(node, idx)].push_back(ii(l, 0));
return;
}
int m = (l + r) >> 1;
build_tree(idx, 2 * node, l, m);
build_tree(idx, 2 * node + 1, m + 1, r);
if(!idx){
v[get(2 * node, idx)].push_back(ii(get(node, idx), 0));
v[get(2 * node + 1, idx)].push_back(ii(get(node, idx), 0));
}
else{
v[get(node, idx)].push_back(ii(get(2 * node, idx), 0));
v[get(node, idx)].push_back(ii(get(2 * node + 1, idx), 0));
}
}

void edge_adder(int idx, int node, int l, int r, int a, int b, int vertex){
if(b < l || r < a)
return;
if(a <= l && r <= b){
if(!idx)
v[get(node, idx)].push_back(ii(vertex, 1));
else
v[vertex].push_back(ii(get(node, idx), 1));
return;
}
int m = (l + r) >> 1;
edge_adder(idx, 2 * node, l, m, a, b, vertex);
edge_adder(idx, 2 * node + 1, m + 1, r, a, b, vertex);
}


void dijkstra(int s)
{
for (int i = 0; i < curr; ++i) D[i] = INT_MAX;
priority_queue <ii> pq;
D[s] = 0;
pq.push(make_pair(0 , s));
while(!pq.empty()){
int node = pq.top().second;
long long cost = -pq.top().first;
pq.pop();
if(D[node] < cost){
continue;
}
for(auto it : v[node]){
int next = it.first;
long long d = cost + it.second;
if(spoilt[next])
continue;
if(D[next] > d){
D[next] = d;
pq.push(make_pair(-d , next));
}
}
}
}

int main(){
int i, j, m, a, b, q, t, it;
scanf("%d %d", &n, &m);
for(i = 0; i < m; i++){
scanf("%d %d", &a, &b);
v[a].push_back(ii(b, 2));
v[b].push_back(ii(a, 2));
}
build_tree(0, 1, 1, n);
build_tree(1, 1, 1, n);

curr = 9 * n + 1;
it = 1;
scanf("%d", &q);
while(q--){
scanf("%d", &t);
if(t == 1){
scanf("%d %d", &a, &b);
edge_adder(0, 1, 1, n, a, b, curr);
edge_adder(1, 1, 1, n, a, b, curr);
memo[it++] = curr;
curr++;
}
else if(t == 2){
scanf("%d", &a);
spoilt[memo[a]] = 1;
}
else if(t == 3){
scanf("%d %d", &a, &b);
dijkstra(a);
(D[b] == INT_MAX)
? printf("-1\n")
: printf("%d\n", D[b] / 2);
}
}

return 0;
}