CCCPaste

Untitled

#include 
#include 
//#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int maxn = 30010;
const int logn = 20;
const int INF = 2e9;
int up[maxn][logn], n;
vector> graph[maxn];
int depth[maxn], parent[maxn];
int dp[logn][maxn];
ll dist[maxn];
int max_edge[logn][maxn], min_edge[logn][maxn];
void dfs(int node, int prev, int level) {
    depth[node] = level;
    parent[node] = prev;
    dp[0][node] = prev;
    for(int i = 0; i < (int) graph[node].size(); i++) {
        int neighbour = graph[node][i].first;
        int weight = graph[node][i].second;
        if(prev != neighbour) {
            dist[neighbour] = dist[node] + weight;
            min_edge[0][neighbour] = weight;
            max_edge[0][neighbour] = weight;
            dfs(neighbour, node, level + 1);
        }
    }
}

void preprocess() {
    memset(up, -1, sizeof up);
    
    for(int i = 0; i < n; i++) {
        up[i][0] = parent[i];
        
    }
    for(int j = 1; (1 << j) < n; j++) {
        for(int i = 0; i < n; i++) {
            if(up[i][j - 1] != -1) {
                up[i][j] = up[up[i][j - 1]][j - 1];
            }
        }
    }
  
}
int LCA(int a, int b) {
    if(depth[a] > depth[b]) {
        swap(a, b);
    }
    int diff = depth[b] - depth[a];
    while(diff > 0) {
        int pow = log2(diff);
        b = up[b][pow];
        diff -= (1 << pow);
    }
    if(b == a) {
        return a;
    }
    for(int i = logn - 1; i >= 0; i--) {
        if(up[a][i] != -1 and up[a][i] != up[b][i]) {
            
            a = up[a][i];
            b = up[b][i];
        }
    }
    return parent[a];
}
void preprocess_max_min() {
    for(int i = 1; i < logn; i++) {
        for(int j = 1; j <= n; j++) {
            dp[i][j] = dp[i - 1][dp[i - 1][j]];
            max_edge[i][j] = max(max_edge[i - 1][j], max_edge[i - 1][dp[i - 1][j]]);
            min_edge[i][j] = min(min_edge[i - 1][j], min_edge[i - 1][dp[i - 1][j]]);
        }
    }
}
pair get_max_min_edge(int a, int b) {
    if(depth[b] < depth[a]) {
        swap(a, b);
    }
    int res_min = INF, res_max = -INF;
    int diff = depth[b] - depth[a];
    while(diff > 0) {
        int pow = log2(diff);
        res_max = max(res_max, max_edge[pow][b]);
        res_min = min(res_min, min_edge[pow][b]);
        b = dp[pow][b];
        diff -= (1 << pow);
    }
    while(a != b) {
        int i = log2(depth[a]);
        while(i > 0 and dp[i][a] == dp[i][b]) {
            i--;
        }
        res_max = max(res_max, max_edge[i][a]);
        res_max = max(res_max, max_edge[i][b]);
        
        res_min = min(res_min, min_edge[i][a]);
        res_min = min(res_min, min_edge[i][b]);
        a = dp[i][a];
        b = dp[i][b];
    }
    return make_pair(res_min, res_max);
}
int main() {
    ios_base::sync_with_stdio(false);
    int q;
    cin >> n >> q;
    for(int i = 1; i < n; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        a--; b--;
        graph[a].push_back(make_pair(b, c));
        graph[b].push_back(make_pair(a, c));
    }
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < logn; j++) {
            max_edge[j][i] = -INF;
            min_edge[j][i] = INF;
        }
    }
    dfs(0, -1, 0);
    preprocess();
    preprocess_max_min();
    ll ivan = 0, martin = 0;
    
    for(int i = 1; i <= q; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        a--; b--;
        
        int lca = LCA(a, b);
        ll d = dist[a] + dist[b] - 2LL * dist[lca];
        pair p = get_max_min_edge(a, b);
        
        int neg = -1 * p.first * c;
        int pos = p.second * c;
        ll d1 = d, d2 = d;
        
            d1 -= p.first;
            d1 += neg;
        
        
            d2 -= p.second;
            d2 += pos;
        
        d = max(d1, d2);
        if(i % 2 == 1) {
            ivan += d;
            
        }
        else {
            martin += d;
        }
    }
    if(ivan == martin) {
        cout << "=" << endl;
    }
    else if(ivan > martin) {
        cout << "Ivan " << ivan - martin << endl;
    }
    else {
        cout << "Martin " << martin - ivan << endl;
    }
    return 0;
}