BYRBT

2566

#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
#include<vector>

using namespace std;

const int MAX_SIZE = 12000;
const int INF = 0x3f3f3f3f;

struct Node{
    int l, r;
    Node *left, *right;
    int minn, tag;
};

Node tree[MAX_SIZE * 2 + 10]; int tn;

inline void update(Node* cur, int v){
    if(cur -> tag > v){
    cur -> tag = v;
    cur -> minn = min(cur -> minn, v);
    }
}

inline void pushDown(Node* cur){
    if(cur -> tag != INF){
    if(cur -> l != cur -> r){
        update(cur -> left, cur -> tag);
        update(cur -> right, cur -> tag);
    }
    cur -> tag = INF;
    }
}

Node* build(int l, int r){
    Node* cur = tree + (tn ++);
    cur -> l = l;
    cur -> r = r;
    cur -> minn = cur -> tag = INF;
    if(l != r){
    int mid = (l + r) >> 1;
    cur -> left = build(l, mid);
    cur -> right = build(mid + 1, r);
    }
    return cur;
}

Node* sroot;

struct O{
    int id, co;
};

vector<int> event[MAX_SIZE + 10];
multiset<int> s[MAX_SIZE * 2 + 10];
int val[MAX_SIZE * 2 + 10], vn;
int data[MAX_SIZE + 10], n;
int nodes[MAX_SIZE + 10], nxt[MAX_SIZE * 2 + 10], to[MAX_SIZE * 2 + 10], en;
int len[MAX_SIZE * 2 + 10];
int m;
bool vis[MAX_SIZE + 10];
int root, minn, tot, size[MAX_SIZE + 10];
O cg[MAX_SIZE + 10];
int dist[MAX_SIZE + 10], clist[MAX_SIZE + 10], cn;
int cco[MAX_SIZE + 10];
int pre[MAX_SIZE * 2 + 10], tVal[MAX_SIZE * 2 + 10];

inline void addEdge(int f, int t, int w){
    ++ en;
    to[en] = t;
    len[en] = w;
    nxt[en] = nodes[f];
    nodes[f] = en;
}

void dfs(int cur, int fa){
    size[cur] = 1;
    for(int e = nodes[cur]; e; e = nxt[e]){
    if(to[e] == fa || vis[to[e]])
        continue;
    dfs(to[e], cur);
    size[cur] += size[to[e]];
    }
}

void findRoot(int cur, int fa){
    int maxn = tot - size[cur];
    for(int e = nodes[cur]; e; e = nxt[e]){
    if(to[e] == fa || vis[to[e]])
        continue;
    if(size[to[e]] > maxn)
        maxn = size[to[e]];
    findRoot(to[e], cur);
    }
    if(maxn < minn){
    minn = maxn;
    root = cur;
    }
}

void dfsDist(int cur, int fa){
    int si = (int)event[cur].size();
    for(int i = 0; i < si; i ++)
    clist[++ cn] = event[cur][i];
    cco[cur] = data[cur];
    int p = lower_bound(val, val + vn, data[cur]) - val;
    s[p].insert(dist[cur]);
    if((int)s[p].size() > 1){
    set<int>::iterator it = s[p].begin();
    int d = *it;
    ++ it;
    d += *it;
    if(tVal[p] > d)
        tVal[p] = d;
    }
    for(int e = nodes[cur]; e; e = nxt[e]){
    if(to[e] == fa || vis[to[e]])
        continue;
    dist[to[e]] = dist[cur] + len[e];
    dfsDist(to[e], cur);
    }
}

void change(Node* cur, int l, int r, int v){
    if(cur -> l == l && cur -> r == r){
    update(cur, v);
    return;
    }
    pushDown(cur);
    int mid = (cur -> l + cur -> r) >> 1;
    if(r <= mid)
    change(cur -> left, l, r, v);
    else if(l > mid)
    change(cur -> right, l, r, v);
    else{
    change(cur -> left, l, mid, v);
    change(cur -> right, mid + 1, r, v);
    }
    cur -> minn = min(cur -> left -> minn, cur -> right -> minn);
}

void clear(int cur, int fa){
    int p = lower_bound(val, val + vn, cco[cur]) - val;
    s[p].clear();
    p = lower_bound(val, val + vn, data[cur]) - val;
    change(sroot, pre[p], m, tVal[p]);
    pre[p] = 0; tVal[p] = INF;
    for(int e = nodes[cur]; e; e = nxt[e]){
    if(to[e] == fa || vis[to[e]])
        continue;
    clear(to[e], cur);
    }
}

void work(int cur){
    dfs(cur, 0);
    tot = size[cur];
    minn = INF;
    findRoot(cur, 0);
    cur = root;
    dist[cur] = 0;
    cn = 0;
    dfsDist(cur, 0);
    sort(clist + 1, clist + cn + 1);
    for(int i = 1; i <= cn; i ++){
    int t = clist[i];
    int p;
    p = lower_bound(val, val + vn, cco[cg[t].id]) - val;
    s[p].erase(s[p].find(dist[cg[t].id]));
    int d;
    if((int)s[p].size() > 1){
        set<int>::iterator it = s[p].begin();
        d = *it;
        ++ it;
        d += *it;
    } else
        d = INF;
    if(pre[p] != t){
        change(sroot, pre[p], t - 1, tVal[p]);
        pre[p] = t;
        tVal[p] = d;
    } else
        tVal[p] = min(tVal[p], d);
    cco[cg[t].id] = cg[t].co;
    p = lower_bound(val, val + vn, cco[cg[t].id]) - val;
    s[p].insert(dist[cg[t].id]);
    if((int)s[p].size() > 1){
        set<int>::iterator it = s[p].begin();
        d = *it;
        ++ it;
        d += *it;
    } else
        d = INF;
    if(pre[p] != t){
        change(sroot, pre[p], t - 1, tVal[p]);
        pre[p] = t;
        tVal[p] = d;
    } else
        tVal[p] = min(tVal[p], d);
    }
    //   s[0].clear();
    for(int i = 1; i <= cn; i ++){
    int t = clist[i];
    int p = lower_bound(val, val + vn, cg[t].co) - val;
    change(sroot, pre[p], m, tVal[p]);
    pre[p] = 0;
    tVal[p] = INF;
    }
    clear(cur, 0);
    vis[cur] = true;
    for(int e = nodes[cur]; e; e = nxt[e]){
    if(!vis[to[e]])
        work(to[e]);
    }
}

void print(Node* cur){
    if(cur -> l == cur -> r){
    if(cur -> minn == INF)
        printf("-1\n");
    else
        printf("%d\n", cur -> minn);
    return;
    }
    pushDown(cur);
    print(cur -> left);
    print(cur -> right);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++){
    scanf("%d", data + i);
    val[vn ++] = data[i];
    }
    for(int i = 1; i < n; i ++){
    int a, b, w;
    scanf("%d%d%d", &a, &b, &w);
    addEdge(a, b, w);
    addEdge(b, a, w);
    }
    scanf("%d", &m);
    for(int i = 1; i <= m; i ++){
    scanf("%d%d", &cg[i].id, &cg[i].co);
    event[cg[i].id].push_back(i);
    val[vn ++] = cg[i].co;
    }
    sort(val, val + vn);
    vn = unique(val, val + vn) - val;
    sroot = build(0, m);
    memset(tVal, INF, sizeof(tVal));
    work(1);
    for(int i = 0; i < vn; i ++)
    s[0].insert(INF);
    memset(pre, INF, sizeof(pre));
    print(sroot);
//    printf("%d\n", pre[2]);

    return 0;
}
View Code

 

posted @ 2014-12-16 19:24 zhonghaoxi 阅读(...) 评论(...) 编辑 收藏
BYRBT