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

Simple Text Editor

In this challenge, you must implement a simple text editor. Initially, your editor contains an empty string, S. You must perform Q operations of the following 4 types: 1. append(W) - Append W string to the end of S. 2 . delete( k ) - Delete the last k characters of S. 3 .print( k ) - Print the kth character of S. 4 . undo( ) - Undo the last (not previously undone) operation of type 1 or 2,

View Solution →

Poisonous Plants

There are a number of plants in a garden. Each of the plants has been treated with some amount of pesticide. After each day, if any plant has more pesticide than the plant on its left, being weaker than the left one, it dies. You are given the initial values of the pesticide in each of the plants. Determine the number of days after which no plant dies, i.e. the time after which there is no plan

View Solution →

AND xor OR

Given an array of distinct elements. Let and be the smallest and the next smallest element in the interval where . . where , are the bitwise operators , and respectively. Your task is to find the maximum possible value of . Input Format First line contains integer N. Second line contains N integers, representing elements of the array A[] . Output Format Print the value

View Solution →

Waiter

You are a waiter at a party. There is a pile of numbered plates. Create an empty answers array. At each iteration, i, remove each plate from the top of the stack in order. Determine if the number on the plate is evenly divisible ith the prime number. If it is, stack it in pile Bi. Otherwise, stack it in stack Ai. Store the values Bi in from top to bottom in answers. In the next iteration, do the

View Solution →

Queue using Two Stacks

A queue is an abstract data type that maintains the order in which elements were added to it, allowing the oldest elements to be removed from the front and new elements to be added to the rear. This is called a First-In-First-Out (FIFO) data structure because the first element added to the queue (i.e., the one that has been waiting the longest) is always the first one to be removed. A basic que

View Solution →

Castle on the Grid

You are given a square grid with some cells open (.) and some blocked (X). Your playing piece can move along any row or column until it reaches the edge of the grid or a blocked cell. Given a grid, a start and a goal, determine the minmum number of moves to get to the goal. Function Description Complete the minimumMoves function in the editor. minimumMoves has the following parameter(s):

View Solution →