Header Ad

HackerEarth Weird Graph Query problem solution

In this HackerEarth Weird Graph Query problem solution, We are given a connected undirected weighted graph of N nodes and M edges. We are then given Q queries wherein each query we are given integers U, L, R, K. For every query we have to report the smallest integer C such that there are at least K nodes x such that L <= x <= R and the shortest distance from x to U is not more than C. 


HackerEarth Weird Graph Query problem solution


HackerEarth Weird Graph Query problem solution.

#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <queue>
#include <deque>
#include <iomanip>
#include <cmath>
#include <set>
#include <stack>
#include <map>
#include <unordered_map>

#define FOR(i,n) for(int i=0;i<n;i++)
#define FORE(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
//#define int long long
#define ld long double
#define vi deque<int>
#define pb push_back
#define ff first
#define ss second
#define ii pair<int,int>
#define iii pair<int,ii>
#define il pair<int,ll>
#define li pair<ll,int>
#define pll pair<ll,ll>
#define _path pair<ll,pair<ll,int> >
#define vv deque
using namespace std;

const int MAXN = 1000+5;
const int INF = 1e9;

struct Node{
int left;
int right;
int data;
Node(){
left = -1;
right = -1;
data = 0;
}
};
Node buf[2000*1000*10];
int PTR;
int get(){
return PTR++;
}
int get(int a,int b,int c){
buf[PTR].left = a;
buf[PTR].right = b;
buf[PTR].data = c;
return PTR++;
}

inline void expand(int node){
if(buf[node].left == -1)buf[node].left = get();
if(buf[node].right == -1)buf[node].right = get();
}
int update(int node,int ss,int se,int i,int val){
if(i < ss or i > se)return node;
if(ss == se){
return get(-1,-1,val);
}
expand(node);

int mid = (ss+se)/2;
int x = update(buf[node].left,ss,mid,i,val);
int y = update(buf[node].right,mid+1,se,i,val);
return get(x,y,buf[x].data + buf[y].data);
}
int get(int node,int ss,int se,int l,int r){
if(r < ss or l > se or node == -1)return 0;
if(l <= ss and se <= r)return buf[node].data;
int mid = (ss+se)/2;
return get(buf[node].left,ss,mid,l,r) + get(buf[node].right,mid+1,se,l,r);
}

vv<ii> g[MAXN];
int dist[MAXN][MAXN];
vv<ii> allversions[MAXN];



void dijkstra(int source,int n){
priority_queue<ii,vv<ii>,greater<ii> > pq;
FOR(i,n)dist[source][i] = INF;
pq.push({0,source});
while(!pq.empty()){
auto item = pq.top();pq.pop();

if(dist[source][item.ss] <= item.ff)continue;
dist[source][item.ss] = item.ff;
for(auto e: g[item.ss]){
if(item.ss+e.ss >= dist[source][e.ff])continue;
pq.push({item.ff + e.ss,e.ff});
}
}
}

void buildPersSegtree(int x,int n){
map<int,vi> all;
FOR(i,n)all[dist[x][i]].pb(i);


allversions[x].pb({0,get()});

for(auto e: all){
int id = allversions[x].back().ss;
for(auto f: e.ss){
id = update(id,0,MAXN,f,1);
}
allversions[x].pb({e.ff,id});
}
}


bool checkAnswer(int nodeU,int l,int r,int id,int k){
return get(allversions[nodeU][id].ss,0,MAXN,l,r) >= k;
}

int getAnswer(int node,int l,int r,int k){
int low = 0;
int high = allversions[node].size();
high--;
int best = allversions[node].back().ff;

while(low <= high){
int mid = (low + high)/2;
if(checkAnswer(node,l,r,mid,k)){
best = min(best,allversions[node][mid].ff);
high = mid -1;
}else{
low = mid+1;
}
}

return best;
}


void solve(){
int n,m;
cin >> n >> m;
FOR(i,m){
int a,b,c;
cin >> a >> b >> c;
a--;b--;
g[a].pb({b,c});
g[b].pb({a,c});
}
FOR(i,n)dijkstra(i,n);
FOR(i,n)buildPersSegtree(i,n);

int q;
cin >> q;
FOR(i,q){
int u,l,r,k;
cin >> u >> l >> r >> k;
u--;l--;r--;
cout << getAnswer(u,l,r,k) << endl;
}
}


int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);

int t = 1;
// cin >> t;
while(t--){
solve();
}
return 0;
}

Post a Comment

0 Comments