Network administration


Problem Statement :


Time Limits C:5, Cpp:5, C#:6, Java:8, Php:18, Ruby:20, Python:20, Perl:18, Haskell:10, Scala:14, Javascript:20, Pascal:5

Like every IT company, the Uplink Corporation has its own network. But, unlike the rest of the companies around the world, Uplink's network is subject to very specific restrictions:

Any pair of servers within the network should be directly connected by at most 1 link.
Each link is controlled by some specific network administrator.
No server has more than 2 links connected to it, that are controlled by the same administrator.
For easier management, links controlled by some administrator cannot be redundant (this is, removing any link will disconnect some two previously connected servers)
Notice that 2 connected servers might not have any direct link between them. Furthermore, in order to keep the network in a secured status, Uplink directives periodically try to perform some modifications over the network to mislead hackers. The problem is, having such a huge network, they need a software to efficiently simulate the network status after any of such modifications. You have been assigned to write the core section of that software.

Operations performed by the directives are:

Change the administrator assigned to some particular link.
Place some number of security devices along a particular link.
Also, given a network administrator, they would like to know how many devices are in the path created by links controlled by that administrator (if any) between 2 servers.


Input Format


Input begins with a line containing 4 integers  separated by a single whitespace, denoting the number of servers, links, network administrators and transformations, respectively.  lines follow each one with 3 integers  and , saying that there is a link between server  and server , and that link is controlled by administrator . Initially, network topology fulfills the restrictions described above and there is no security device along any link. Remaining  lines in the input follow one the next formats:

   
meaning that link between server  and server   is requested to be assigned to administrator 

   
meaning that the number of security devices along the link between server  and server   will be fixed to , removing any existing devices on this link before the operation. The involved link will always exist.

   
meaning that directives want to know the number of security devices placed along the path between server  and server , just considering links controlled by administrator .

Output Format

For each network transformation in the form     you should output:

"Wrong link" if there is no direct link between server  and server .
"Already controlled link" if the requested link does exist, but it is already controlled by administrator .
"Server overload" if administrator  already controls 2 links connected to one of the involved servers.
"Network redundancy" if the requested assignment creates no new connection considering just the links controlled by .
"Assignment done" if none of the above conditions holds. In this case, link directly connecting  with  is assigned to .
For each network transformation in the form     you should output:

"No connection" if there is no path between the requested servers considering just the links controlled by .
" security devices placed" where D is the number of security devices placed so far on the existing connection between the requested servers considering just the links controlled by .


Constraints


1  <=   S  <=   10^5
1  <=   L   <=  5 * 10^5
1  <=   A  <=  10^2
1  <=   T  <=   5 * 10^5
1  <=  x  <=  2000



Solution :



title-img


                            Solution in C :

In   C++  :







#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <cctype>
#include <cassert>
#include <limits>
#include <functional>
#include <bitset>
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
#if defined(_MSC_VER) || __cplusplus > 199711L
#define aut(r,v) auto r = (v)
#else
#define aut(r,v) typeof(v) r = (v)
#endif
#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#define mset(m,v) memset(m,v,sizeof(m))
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
using namespace std;
typedef vector<int> vi; typedef pair<int,int> pii; 
typedef vector<pair<int,int> > vpii;
typedef long long ll; typedef vector<long long> vl; 
typedef pair<long long,long long> pll; 
typedef vector<pair<long long,long long> > vpll;
typedef vector<string> vs; 
typedef long double ld;
template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }
template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }


unsigned xor128() {
static unsigned x = 123456789, y = 362436069, z = 521288629, w = 88675123;
unsigned t = x ^ (x << 11);
x = y; y = z; z = w;
return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
}

template<typename Derived>
struct PNodeBase {
Derived *left, *right, *parent;
int size;
PNodeBase(): left(NULL), right(NULL), parent(NULL), size(1) { }
inline Derived *update() {
size = (!left ? 0 : left->size) + 1 + (!right ? 0 : right->size);
return derived();
}
inline void propagate() { }
inline Derived *linkl(Derived *c) {
if(left = c) c->parent = derived();
return derived()->update();
}
inline Derived *linkr(Derived *c) {
if(right = c) c->parent = derived();
return derived()->update();
}
inline Derived *linklr(Derived *l, Derived *r) {
if(left = l) l->parent = derived();
if(right = r) r->parent = derived();
return derived()->update();
}
static inline Derived *cut(Derived *t) {
if(t) t->parent = NULL;
return t;
}
private:
inline Derived *derived() 
{ return static_cast<Derived*>(this); }
};
struct Node : PNodeBase<Node> {
typedef PNodeBase<Node> Base;
int weight, sum;
bool reversed;
Node(): weight(0), sum(0), reversed(false) { }
Node *update() {
sum = (!left ? 0 : left->sum) + weight + (!right ? 0 : right->sum);
return static_cast<Base*>(this)->update();
}
inline void propagate() {
if(reversed) {
swap(left, right);
if(left != 0) left->reversed ^= true;
if(right != 0) right->reversed ^= true;
reversed = false;
}
return static_cast<Base*>(this)->propagate();
}
};

struct PRBSTBase {
typedef Node *Ref;
static int size(Ref t) { return !t ? 0 : t->size; }
static Ref join(Ref l, Ref r) {
if(!l) return r;
if(!r) return l;
if((int)(xor128() % (l->size + r->size)) < l->size) {
l->propagate();
return l->linkr(join(Node::cut(l->right), r));
}else {
r->propagate();
return r->linkl(join(l, Node::cut(r->left)));
}
}
typedef pair<Ref,Ref> RefPair;
static RefPair split(Ref t, int k) {
if(!t) return RefPair((Ref)NULL, (Ref)NULL);
t->propagate();
int s = size(t->left);
if(k <= s) {
RefPair p = split(Node::cut(t->left), k);
return RefPair(p.first, t->linkl(p.second));
}else {
RefPair p = split(Node::cut(t->right), k - s - 1);
return RefPair(t->linkr(p.first), p.second);
}
}
static Ref insert(Ref t, int k, Ref n) {
if(!t) return n;
if(xor128() % (t->size + 1) == 0) {
RefPair p = split(t, k);
return n->linklr(p.first, p.second);
}
t->propagate();
int s = size(t->left);
if(k <= s)
return t->linkl(insert(Node::cut(t->left), k, n));
else
return t->linkr(insert(Node::cut(t->right), k - s - 1, n));
}
static RefPair remove(Ref t, int k) {
if(!t) return RefPair((Ref)NULL, (Ref)NULL);
t->propagate();
int s = size(t->left);
if(k < s) {
RefPair p = remove(Node::cut(t->left), k);
return RefPair(t->linkl(p.first), p.second);
}else if(k > s) {
RefPair p = remove(Node::cut(t->right), k - s - 1);
return RefPair(t->linkr(p.first), p.second);
}else {
Ref a = join(Node::cut(t->left), Node::cut(t->right));
return RefPair(a, t->linklr(NULL, NULL));
}
}
static Ref index(Ref t, int k) {
if(!t) return NULL;
t->propagate();
int s = size(t->left);
if(k < s)
return index(t->left, k);
else if(k > s)
return index(t->right, k - s - 1);
else
return t;
}
static void topDown(Ref t) {
Ref nodes[128]; int k = 0;
for(Ref u = t; u != 0; u = u->parent)
nodes[k ++] = u;
while(k > 0)
nodes[-- k]->propagate();
}
static pair<Ref,int> findRoot(Ref t) {
if(!t) return make_pair((Ref)NULL, 0);
topDown(t);
int k = size(t->left);
while(true) {
Ref p = t->parent;
if(!p) return make_pair(t, k);
if(p->right == t)
k += size(p->left) + 1;
t = p;
}
}
};
typedef PRBSTBase BST;

struct Vector2 {
int a[2], s;
Vector2(): s(0) { }
int operator[](int i) const { assert(i < s); return a[i]; }
void push_back(int x) { a[s ++] = x; }
void erase(int x) { s = remove(a, a + s, x) - a; }
int size() const { return s; }
bool empty() const { return s == 0; }
};

void link(int i, int a, int x, int y, 
const vector<vector<Vector2> > &g, vector<Node> &nodes) {
Node *t = &nodes[i];
assert(BST::size(t) == 1);
if(!g[a][x].empty()) {
Node *l = &nodes[g[a][x][0]];
pair<Node*,int> pl = BST::findRoot(l);
if(pl.second != BST::size(pl.first) - 1) {
assert(pl.second == 0);
pl.first->reversed ^= true;
}
t = BST::join(pl.first, t);
}
if(!g[a][y].empty()) {
Node *r = &nodes[g[a][y][0]];
pair<Node*,int> pr = BST::findRoot(r);
if(pr.second != 0) {
assert(pr.second == BST::size(pr.first) - 1);
pr.first->reversed ^= true;
}
t = BST::join(t, pr.first);
}
}

int main() {
int S, L, AA, T;
scanf("%d%d%d%d", &S, &L, &AA, &T);
vector<vector<Vector2> > g(AA, vector<Vector2>(S));
map<pii,int> links;
vector<pii> edges(L);
vector<Node> nodes(L);
vector<int> admin(L, -1);
rep(i, L) {
int x, y, a;
scanf("%d%d%d", &x, &y, &a), -- x, -- y, -- a;
if(x > y) swap(x, y);

link(i, a, x, y, g, nodes);

g[a][x].push_back(i);
g[a][y].push_back(i);

edges[i] = mp(x, y);
links[mp(x, y)] = i;
admin[i] = a;
}
const char *msgs[9] = {
"?????\n",
"Wrong link\n",
"Already controlled link\n",
"Server overload\n",
"Network redundancy\n",
"Assignment done\n",
"",
"No connection\n",
"%d security devices placed\n",
};
rep(ii, T) {
int ty, A, B, x, a;
scanf("%d%d%d%d", &ty, &A, &B, &x), -- A, -- B;
a = x - 1;
if(A > B) swap(A, B);

int result; int ans = -1;
if(ty == 1) {
auto it = links.find(mp(A, B));
if(it == links.end()) {
result = 1;
}else if(admin[it->second] == a) {
result = 2;
}else if(g[a][A].size() >= 2 || g[a][B].size() >= 2) {
result = 3;
}else {
int i = it->second, pa = admin[i];
Node *tt = &nodes[i];
pair<Node*,int> p = BST::findRoot(tt);
Node *t = p.first;

{
Node *l = g[a][A].empty() ? 0 :
 BST::findRoot(&nodes[g[a][A][0]]).first;
Node *r = g[a][B].empty() ? 0 : 
BST::findRoot(&nodes[g[a][B][0]]).first;
if(l != 0 && r != 0 && l == r) {
result = 4;
goto next;
}
}

//??admin?????????
if(p.second != 0) {
int j = BST::index(p.first, p.second - 1) - &nodes[0];
if(admin[j] == pa) {
p.first = BST::split(p.first, p.second).second;
p.second = 0;
}
}
if(p.second != BST::size(p.first) - 1) {
int j = BST::index(p.first, p.second + 1) - &nodes[0];
if(admin[j] == pa) {
p.first = BST::split(p.first, p.second + 1).first;
}
}
g[pa][A].erase(i);
g[pa][B].erase(i);

link(i, a, A, B, g, nodes);

g[a][A].push_back(i);
g[a][B].push_back(i);

admin[i] = a;

result = 5;
}
}else if(ty == 2) {
if(!links.count(mp(A, B))) abort();
int i = links[mp(A, B)];
Node *tt = &nodes[i];
pair<Node*,int> p = BST::findRoot(tt);
Node *u = BST::remove(p.first, p.second).first;
tt->weight = x;
tt->update();
BST::insert(u, p.second, tt);
result = 6;
}else if(ty == 3) {
if(A == B) {
result = 8, ans = 0;
goto next;
}
if(g[a][A].empty() || g[a][B].empty()) {
result = 7;
goto next;
}
Node *l = &nodes[g[a][A][0]];
Node *r = &nodes[g[a][B][0]];
pair<Node*,int> pl = BST::findRoot(l);
pair<Node*,int> pr = BST::findRoot(r);
if(pl.first != pr.first) {
result = 7;
goto next;
}
if(g[a][A].size() == 2) {
Node *l1 = &nodes[g[a][A][1]];
pair<Node*,int> pl1 = BST::findRoot(l1);
if(pl1.first != pl.first) abort();
if(abs(pl.second - pr.second) > abs(
    pl1.second - pr.second))
l = l1, pl = pl1;
}
if(g[a][B].size() == 2) {
Node *r1 = &nodes[g[a][B][1]];
pair<Node*,int> pr1 = BST::findRoot(r1);
if(pr1.first != pr.first) abort();
if(abs(pl.second - pr.second) > abs(
    
    pl.second - pr1.second))
r = r1, pr = pr1;
}
Node *t = pl.first;
int L = pl.second, R = pr.second;
if(L > R) swap(L, R);
pair<Node*,Node*> p = BST::split(t, R + 1);
pair<Node*,Node*> q = BST::split(p.first, L);

Node *u = q.second;
result = 8;
ans = u->sum;

t = BST::join(BST::join(q.first, q.second), p.second);
}
next:;
printf(msgs[result], ans);
}
return 0;
}









In   Java :






import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;

public class HR_net_admin {

static class Node {
Node l = null, r = null, p = null;
boolean reversed = false;
int value = 0, sum = 0;
int u, v, admin;

Node(int u, int v, int admin) {
this.u = u;
this.v = v;
this.admin = admin;
}
}

static int sum(Node n) {
return n == null ? 0 : n.sum;
}

static void fixUp(Node n) {
n.sum = n.value + sum(n.l) + sum(n.r);
}

static void fixDown(Node n) {
if (n.reversed) {
Node tmp = n.l;
n.l = n.r;
n.r = tmp;
int ti = n.u;
n.u = n.v;
n.v = ti;
if (n.l != null) {
n.l.reversed ^= true;
}
if (n.r != null) {
n.r.reversed ^= true;
}
n.reversed = false;
}
}

static void rotate(Node x) {
Node y = x.p;
x.p = y.p;
if (y.p != null) {
if (y == y.p.l) {
y.p.l = x;
} else {
y.p.r = x;
}
}
y.p = x;
if (x == y.l) {
y.l = x.r;
if (y.l != null) {
y.l.p = y;
}
x.r = y;
} else {
y.r = x.l;
if (y.r != null) {
y.r.p = y;
}
x.l = y;
}
fixUp(y);
fixUp(x);
}

static Node splay(Node x) {
while (x.p != null) {
if (x.p.p != null) {
fixDown(x.p.p);
}
fixDown(x.p);
fixDown(x);
if (x.p.p == null) {
rotate(x);
} else {
if (x == x.p.l && x.p == x.p.p.l || x == x.p.r && x.p == x.p.p.r) {
rotate(x.p);
rotate(x);
} else {
rotate(x);
rotate(x);
}
}
}
return x;
}

static Node join(Node l, Node x, Node r) {
x.reversed = false;
x.l = l;
x.r = r;
if (l != null) {
l.p = x;
}
if (r != null) {
r.p = x;
}
fixUp(x);
return x;
}

static Node q, r;

static void split(Node x) {
splay(x);
fixDown(x);
if (x.l != null) {
x.l.p = null;
}
if (x.r != null) {
x.r.p = null;
}
x.p = null;
q = x.l;
r = x.r;
x.l = x.r = null;
fixUp(x);
}

static Node min(Node n) {
fixDown(n);
while (n.l != null) {
n = n.l;
fixDown(n);
}
splay(n);
return n;
}

static Node max(Node n) {
fixDown(n);
while (n.r != null) {
n = n.r;
fixDown(n);
}
splay(n);
return n;
}

public static void solve(Input in, PrintWriter out)
 throws IOException {
int n = in.nextInt(); // servers
int m = in.nextInt(); // links
int k = in.nextInt(); // admins
int q = in.nextInt(); // queries
HashMap<Integer, Node>[] edges = new HashMap[n];
HashMap<Integer, Node[]>[] admins = new HashMap[n];
for (int i = 0; i < n; ++i) {
edges[i] = new HashMap<>();
admins[i] = new HashMap<>();
}
for (int i = 0; i < m; ++i) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int a = in.nextInt() - 1;
Node e = new Node(u, v, a);
edges[u].put(v, e);
edges[v].put(u, e);
insert(e, admins);
}
for (int i = 0; i < q; ++i) {
int t = in.nextInt();
if (t == 1) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int a = in.nextInt() - 1;
if (!edges[u].containsKey(v)) {
out.println("Wrong link");
continue;
}
Node e = edges[u].get(v);
if (e.admin == a) {
out.println("Already controlled link");
continue;
}
Node l = null, r = null;
if (admins[u].containsKey(a)) {
Node[] ar = admins[u].get(a);
if (ar.length > 1) {
out.println("Server overload");
continue;
}
if (ar.length == 1) {
l = ar[0];
}
}
if (admins[v].containsKey(a)) {
Node[] ar = admins[v].get(a);
if (ar.length > 1) {
out.println("Server overload");
continue;
}
if (ar.length == 1) {
r = ar[0];
}
}
if (l != null && r != null && min(splay(l)) == min(splay(r))) {
out.println("Network redundancy");
continue;
}
admins[u].put(e.admin, remove(admins[u].get(e.admin), e));
admins[v].put(e.admin, remove(admins[v].get(e.admin), e));
split(e);
e.admin = a;
insert(e, admins);
out.println("Assignment done");
} else if (t == 2) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int x = in.nextInt();
if (!edges[u].containsKey(v)) {
throw new AssertionError();
}
Node e = edges[u].get(v);
splay(e);
e.value = x;
fixUp(e);
} else if (t == 3) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int a = in.nextInt() - 1;
Node l = any(u, a, admins);
Node r = any(v, a, admins);
if (l == null || r == null || min(splay(l)) != min(splay(r))) {
out.println("No connection");
continue;
}
int prefixU = prefix(u, a, l);
int prefixV = prefix(v, a, r);
out.println(Math.abs(prefixU - prefixV) + " security devices placed");
}
}
}

private static int prefix(int u, int a, Node e) {
splay(e);
fixDown(e);
if (u == e.u) {
return sum(e.l);
} else if (u == e.v) {
return sum(e.l) + e.value;
} else {
throw new AssertionError();
}
}

private static Node any(int u,
 int a, HashMap<Integer, Node[]>[] admins) {
Node[] ar = admins[u].get(a);
return ar == null || ar.length == 0 ? null : ar[0];
}

private static Node insert(Node e, 
HashMap<Integer, Node[]>[] admins) {
int u = e.u;
int v = e.v;
fixDown(e);
int a = e.admin;
Node l = null, r = null;
if (admins[u].containsKey(a)) {
Node[] ar = admins[u].get(a);
if (ar.length > 1) {
throw new AssertionError();
}
if (ar.length == 1) {
l = ar[0];
}
}
if (admins[v].containsKey(a)) {
Node[] ar = admins[v].get(a);
if (ar.length > 1) {
throw new AssertionError();
}
if (ar.length == 1) {
r = ar[0];
}
}
if (l != null && r != null && min(splay(l)) == min(splay(r))) {
throw new AssertionError();
}
if (l != null && max(splay(l)).v != u) {
splay(l).reversed ^= true;
if (max(splay(l)).v != u) {
throw new AssertionError();
}
}
if (r != null && min(splay(r)).u != v) {
splay(r).reversed ^= true;
if (min(splay(r)).u != v) {
throw new AssertionError();
}
}
admins[u].put(a, append(admins[u].get(a), e));
admins[v].put(a, append(admins[v].get(a), e));
return join(l, e, r);
}

private static Node[] append(Node[] ar, Node e) {
if (ar == null) {
return new Node[] {e};
}
ar = Arrays.copyOf(ar, ar.length + 1);
ar[ar.length - 1] = e;
return ar;
}

private static Node[] remove(Node[] ar, Node e) {
if (ar == null) {
throw new AssertionError();
}
Node[] ar1 = new Node[ar.length - 1];
int len = 0;
for (int i = 0; i < ar.length; ++i) {
if (ar[i] != e) {
ar1[len++] = ar[i];
}
}
if (len != ar1.length) {
throw new AssertionError();
}
return ar1;
}

public static void main(String[] args)
throws IOException {
PrintWriter out = new PrintWriter(System.out);

solve(new Input(new BufferedReader(
    new InputStreamReader(System.in))), out);
out.close();
}

private static boolean cdfs(int i, int p, int[][] g, boolean[] col, int c) {
int count = 0;
col[i] = true;
for (int j = 0; j < g.length; ++j) {
if (g[i][j] != c || j == p) {
continue;
}
if (col[j] || !cdfs(j, i, g, col, c)) {
return false;
}
count++;
}
return count <= (p == -1 ? 2 : 1);
}

public static void solveSlow(Input in,
 PrintWriter out) throws IOException {
int n = in.nextInt(); // servers
int m = in.nextInt(); // links
int k = in.nextInt(); // admins
int q = in.nextInt(); // queries
int[][] g = new int[n][n];
for (int[] ar : g) {
Arrays.fill(ar, -1);
}
int[][] c = new int[n][n];
for (int i = 0; i < m; ++i) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int a = in.nextInt() - 1;
g[u][v] = g[v][u] = a;
}
for (int it = 0; it < q; ++it) {
int t = in.nextInt();
if (t == 1) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int a = in.nextInt() - 1;
if (g[u][v] == -1) {
out.println("Wrong link");
continue;
}
if (g[u][v] == a) {
out.println("Already controlled link");
continue;
}
int uc = 0, vc = 0;
for (int i = 0; i < n; ++i) {
if (g[u][i] == a) {
uc++;
}
if (g[v][i] == a) {
vc++;
}
}
if (uc == 2 || vc == 2) {
out.println("Server overload");
continue;
}
int[] d = new int[n];
Arrays.fill(d, -1);
dfs(u, 0, a, g, c, d);
if (d[v] != -1) {
out.println("Network redundancy");
continue;
}
g[u][v] = g[v][u] = a;
out.println("Assignment done");
} else if (t == 2) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int x = in.nextInt();
c[u][v] = c[v][u] = x;
} else if (t == 3) {
int u = in.nextInt() - 1;
int v = in.nextInt() - 1;
int a = in.nextInt() - 1;
int[] d = new int[n];
Arrays.fill(d, -1);
dfs(u, 0, a, g, c, d);
if (d[v] == -1) {
out.println("No connection");
continue;
}
out.println(d[v] + " security devices placed");
}
}
}

private static void dfs(int i, int dist, int a, 
int[][] g, int[][] c, int[] d) {
if (d[i] != -1) {
return;
}
d[i] = dist;
for (int j = 0; j < g.length; ++j) {
if (g[i][j] == a) {
dfs(j, dist + c[i][j], a, g, c, d);
}
}
}

static class Input {
BufferedReader in;
StringBuilder sb = new StringBuilder();

public Input(BufferedReader in) {
this.in = in;
}

public Input(String s) {
this.in = new BufferedReader(new StringReader(s));
}

public String next() throws IOException {
sb.setLength(0);
while (true) {
int c = in.read();
if (c == -1) {
return null;
}
if (" \n\r\t".indexOf(c) == -1) {
sb.append((char)c);
break;
}
}
while (true) {
int c = in.read();
if (c == -1 || " \n\r\t".indexOf(c) != -1) {
break;
}
sb.append((char)c);
}
return sb.toString();
}

public int nextInt() throws IOException {
return Integer.parseInt(next());
}

public long nextLong() throws IOException {
return Long.parseLong(next());
}

public double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}
}










In    C  :







#include <stdio.h>
#include <stdlib.h>
#define HASH_SIZE 123455
typedef struct _ct_node{
  int x;
  int y;
  int size;
  int priority;
  int a;
  int value;
  int sum;
  int reverse;
  struct _ct_node *left,*right,*parent,*next;
} ct_node;
int sum_link(int x,int y,int z);
void change_link(ct_node *p,int x);
int insert_link(ct_node *p,int x);
void remove_link(ct_node *p);
void find(ct_node *p,int *idx,ct_node **ret);
void insert(ct_node *p);
ct_node* search(int x,int y);
ct_node* merge(ct_node *L,ct_node *R);
int sizeOf(ct_node *root);
int sumOf(ct_node *root);
void recalc(ct_node *root);
void split(int x,ct_node **L,ct_node **R,ct_node *root);
int sum(ct_node *p,int x,int y);
void push(ct_node *root);
ct_node *a[100000][100][2],*hash[HASH_SIZE];

int main(){
  int S,L,A,T,x,y,z,w,i;
  ct_node *p;
  scanf("%d%d%d%d",&S,&L,&A,&T);
  for(i=0;i<L;i++){
    scanf("%d%d%d",&x,&y,&z);
    x--;
    y--;
    z--;
    p=(ct_node*)malloc(sizeof(ct_node));
    p->x=x;
    p->y=y;
    p->size=1;
    p->priority=rand();
    p->a=z;
    p->value=p->sum=p->reverse=0;
    p->left=p->right=p->parent=p->next=NULL;
    insert(p);
    insert_link(p,z);
  }
  while(T--){
    scanf("%d%d%d%d",&w,&x,&y,&z);
    if(w==1){
      p=search(x-1,y-1);
      if(!p)
        p=search(y-1,x-1);
      if(!p)
        printf("Wrong link\n");
      else if(p->a==z-1)
        printf("Already controlled link\n");
      else if(a[x-1][z-1][1] || a[y-1][z-1][1])
        printf("Server overload\n");
      else{
        w=p->a;
        remove_link(p);
        if(insert_link(p,z-1)){
          insert_link(p,w);
          printf("Network redundancy\n");
        }
        else
          printf("Assignment done\n");
      }
    }
    else if(w==2){
      p=search(x-1,y-1);
      if(p)
        change_link(p,z);
      else
        change_link(search(y-1,x-1),z);
    }
    else{
      if(x==y){
        printf("No connection\n");
        continue;
      }
      w=sum_link(x-1,y-1,z-1);
      if(w==-1)
        printf("No connection\n");
      else
        printf("%d security devices placed\n",w);
    }
  }
  return 0;
}
int sum_link(int x,int y,int z){
  int ret,idx1,idx2,idx3,idx4;
  ct_node *p1,*p2,*p3,*p4,*pp1,*pp2;
  p1=a[x][z][0];
  p2=a[x][z][1];
  p3=a[y][z][0];
  p4=a[y][z][1];
  if(!p1 || !p3)
    return -1;
  find(p1,&idx1,&pp1);
  find(p3,&idx3,&pp2);
  idx2=idx4=-1;
  if(p2)
    find(p2,&idx2,&pp1);
  if(p4)
    find(p4,&idx4,&pp2);

/////////////////////
if(idx2!=-1 && !(idx1-idx2==1 || idx2-idx1==1)){
  while(1);
  printf("Oh no. %d %d\n",idx1,idx2);
}
if(idx4!=-1 && !(idx3-idx4==1 || idx4-idx3==1)){
  while(1);
  printf("Oh no. %d %d\n",idx3,idx4);
}
/////////////////////

  if(pp1!=pp2)
    return -1;
  if(idx2==-1 && idx4==-1)
    return pp1->sum;
  if(idx1==idx3)
    return sum(pp1,idx1,idx3);
  else if(idx1<idx3)
    if(idx2==-1)
      if(idx3<idx4)
        return sum(pp1,idx1,idx3);
      else
        return sum(pp1,idx1,idx4);
    else if(idx4==-1)
      if(idx1<idx2)
        return sum(pp1,idx2,idx3);
      else
        return sum(pp1,idx1,idx3);
    else
      if(idx1<idx2)
        if(idx3<idx4)
          return sum(pp1,idx2,idx3);
        else
          return sum(pp1,idx2,idx4);
      else
        if(idx3<idx4)
          return sum(pp1,idx1,idx3);
        else
          return sum(pp1,idx1,idx4);
  else
    if(idx2==-1)
      if(idx3<idx4)
        return sum(pp1,idx4,idx1);
      else
        return sum(pp1,idx3,idx1);
    else if(idx4==-1)
      if(idx1<idx2)
        return sum(pp1,idx3,idx1);
      else
        return sum(pp1,idx3,idx2);
    else
      if(idx1<idx2)
        if(idx3<idx4)
          return sum(pp1,idx4,idx1);
        else
          return sum(pp1,idx3,idx1);
      else
        if(idx3<idx4)
          return sum(pp1,idx4,idx2);
        else
          return sum(pp1,idx3,idx2);
  return ret;
}
void change_link(ct_node *p,int x){
  p->value=x;
  recalc(p);
  for(;p->parent;p=p->parent)
    recalc(p->parent);
  return;
}
int insert_link(ct_node *p,int x){
  int idx1,idx2;
  ct_node *p1,*p2;
  p->a=x;
  if(!a[p->x][x][0] && !a[p->y][x][0]){
    a[p->x][x][0]=p;
    a[p->y][x][0]=p;
    return 0;
  }
  else if(!a[p->x][x][0] && a[p->y][x][0]){
    find(a[p->y][x][0],&idx1,&p1);
    if(idx1)
      merge(p1,p);
    else
      merge(p,p1);
    a[p->x][x][0]=p;
    a[p->y][x][1]=p;
    return 0;
  }
  else if(a[p->x][x][0] && !a[p->y][x][0]){
    find(a[p->x][x][0],&idx1,&p1);
    if(idx1)
      merge(p1,p);
    else
      merge(p,p1);
    a[p->x][x][1]=p;
    a[p->y][x][0]=p;
    return 0;
  }
  find(a[p->x][x][0],&idx1,&p1);
  find(a[p->y][x][0],&idx2,&p2);
  if(p1==p2)
    return 1;
  if(!idx1 && !idx2){
    p1->reverse^=1;
    merge(p1,merge(p,p2));
  }
  else if(!idx1 && idx2)
    merge(p2,merge(p,p1));
  else if(idx1 && !idx2)
    merge(p1,merge(p,p2));
  else{
    p2->reverse^=1;
    merge(p1,merge(p,p2));
  }
  a[p->x][x][1]=p;
  a[p->y][x][1]=p;
  return 0;
}
void remove_link(ct_node *p){
  int idx;
  ct_node *p1,*p2;
  find(p,&idx,&p1);
  split(idx-1,&p1,&p2,p1);
  split(0,&p1,&p2,p2);
  if(a[p->x][p->a][0]==p)
    a[p->x][p->a][0]=a[p->x][p->a][1];
  if(a[p->y][p->a][0]==p)
    a[p->y][p->a][0]=a[p->y][p->a][1];
  a[p->x][p->a][1]=NULL;
  a[p->y][p->a][1]=NULL;
  return;
}
void find(ct_node *p,int *idx,ct_node **ret){
  int d,i;
  for(i=-1;p->parent;p=p->parent){
    if(i==-1)
      if(p->reverse)
        i=sizeOf(p->right);
      else
        i=sizeOf(p->left);
    else
      if(!d && p->reverse)
        i=sizeOf(p->right)+sizeOf(p->left)-i;
      else if(d && !p->reverse)
        i+=sizeOf(p->left)+1;
      else if(d && p->reverse)
        i=sizeOf(p->right)-i-1;
    if(p->parent->left==p)
      d=0;
    else
      d=1;
  }
  if(i==-1)
    if(p->reverse)
      i=sizeOf(p->right);
    else
      i=sizeOf(p->left);
  else
    if(!d && p->reverse)
      i=sizeOf(p->right)+sizeOf(p->left)-i;
    else if(d && !p->reverse)
      i+=sizeOf(p->left)+1;
    else if(d && p->reverse)
      i=sizeOf(p->right)-i-1;
  *idx=i;
  *ret=p;
  return;
}
void insert(ct_node *p){
  int bucket=(p->x+100000LL*p->y)%HASH_SIZE;
  p->next=hash[bucket];
  hash[bucket]=p;
  return;
}
ct_node* search(int x,int y){
  int bucket=(x+100000LL*y)%HASH_SIZE;
  ct_node *t=hash[bucket];
  while(t){
    if(t->x==x && t->y==y)
      return t;
    t=t->next;
  }
  return NULL;
}
ct_node* merge(ct_node *L,ct_node *R){
  if(!L)
    return R;
  if(!R)
    return L;
  if(L->priority>R->priority){
    push(L);
    if(L->right)
      L->right->parent=NULL;
    L->right=merge(L->right,R);
    if(L->right)
      L->right->parent=L;
    recalc(L);
    return L;
  }
  push(R);
  if(R->left)
    R->left->parent=NULL;
  R->left=merge(L,R->left);
  if(R->left)
    R->left->parent=R;
  recalc(R);
  return R;
}
int sizeOf(ct_node *root){
  return (root)?root->size:0;
}
int sumOf(ct_node *root){
  return (root)?root->sum:0;
}
void recalc(ct_node *root){
  root->size=sizeOf(root->left)+sizeOf(root->right)+1;
  root->sum=sumOf(root->left)+sumOf(root->right)+root->value;
  return;
}
void split(int x,ct_node **L,ct_node **R,ct_node *root){
  if(!root){
    *L=*R=NULL;
    return;
  }
  push(root);
  int curIndex=sizeOf(root->left);
  ct_node *t;
  if(curIndex<=x){
    if(root->right)
      root->right->parent=NULL;
    split(x-curIndex-1,&t,R,root->right);
    if(t)
      t->parent=root;
    root->right=t;
    recalc(root);
    *L=root;
  }
  else{
    if(root->left)
      root->left->parent=NULL;
    split(x,L,&t,root->left);
    if(t)
      t->parent=root;
    root->left=t;
    recalc(root);
    *R=root;
  }
  return;
}
int sum(ct_node *p,int x,int y){
  int ret;
  ct_node *p1,*p2;
  split(y,&p2,&p,p);
  split(x-1,&p1,&p2,p2);
  ret=p2->sum;
  merge(p1,merge(p2,p));
  return ret;
}
void push(ct_node *root){
  if(!root || !root->reverse)
    return;
  ct_node *t=root->left;
  root->left=root->right;
  root->right=t;
  root->reverse=0;
  if(root->left)
    root->left->reverse^=1;
  if(root->right)
    root->right->reverse^=1;
  return;
}
                        








View More Similar Problems

Cycle Detection

A linked list is said to contain a cycle if any node is visited more than once while traversing the list. Given a pointer to the head of a linked list, determine if it contains a cycle. If it does, return 1. Otherwise, return 0. Example head refers 1 -> 2 -> 3 -> NUL The numbers shown are the node numbers, not their data values. There is no cycle in this list so return 0. head refer

View Solution →

Find Merge Point of Two Lists

This challenge is part of a tutorial track by MyCodeSchool Given pointers to the head nodes of 2 linked lists that merge together at some point, find the node where the two lists merge. The merge point is where both lists point to the same node, i.e. they reference the same memory location. It is guaranteed that the two head nodes will be different, and neither will be NULL. If the lists share

View Solution →

Inserting a Node Into a Sorted Doubly Linked List

Given a reference to the head of a doubly-linked list and an integer ,data , create a new DoublyLinkedListNode object having data value data and insert it at the proper location to maintain the sort. Example head refers to the list 1 <-> 2 <-> 4 - > NULL. data = 3 Return a reference to the new list: 1 <-> 2 <-> 4 - > NULL , Function Description Complete the sortedInsert function

View Solution →

Reverse a doubly linked list

This challenge is part of a tutorial track by MyCodeSchool Given the pointer to the head node of a doubly linked list, reverse the order of the nodes in place. That is, change the next and prev pointers of the nodes so that the direction of the list is reversed. Return a reference to the head node of the reversed list. Note: The head node might be NULL to indicate that the list is empty.

View Solution →

Tree: Preorder Traversal

Complete the preorder function in the editor below, which has 1 parameter: a pointer to the root of a binary tree. It must print the values in the tree's preorder traversal as a single line of space-separated values. Input Format Our test code passes the root node of a binary tree to the preOrder function. Constraints 1 <= Nodes in the tree <= 500 Output Format Print the tree's

View Solution →

Tree: Postorder Traversal

Complete the postorder function in the editor below. It received 1 parameter: a pointer to the root of a binary tree. It must print the values in the tree's postorder traversal as a single line of space-separated values. Input Format Our test code passes the root node of a binary tree to the postorder function. Constraints 1 <= Nodes in the tree <= 500 Output Format Print the

View Solution →