답안 #96662

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
96662 2019-02-10T16:29:04 Z noneTP Transport (COCI19_transport) C++14
130 / 130
602 ms 25336 KB
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
typedef tuple<int, int, int> tp;
typedef long long LL;
typedef long double LD;
typedef pair<int, int> pii;
typedef pair<int, LL> pil;
typedef pair<LL, int> pli;
typedef pair<LL, LL> pll;
typedef pair<pii, int> piipi;
typedef pair<int, pii> pipii;
typedef pair<pii, pii> piipii;
typedef pair<LL, pii> plpii;
typedef pair<LD, LD> pdd;
typedef pair<LD, int> pdi;
typedef pair<LD, LL> pdl;
typedef pair<int, LD> pid;
typedef pair<LL, LD> pld;
const int mod = 1e9 + 7;
const int hf = 999983;
const int N = 100000;

LL ans = 0;
int A[N+5];

vector<pii> g[N+5];
int par[18][N+5];
int depth[N+5];
bool vis[N+5];

int n = N;
int nn = 0;
int sub[N+5];
int par2[N+5];

void init(int m){
    n = m;
    for(int i=1;i<=n;i++){
        g[i].clear();
        depth[i] = 0;
        vis[i] = 0;
        sub[i] = 0;
        par2[i] = 0;
        for(int j=0;j<18;j++) par[j][i] = 0;
    }
}

void addEdge(int a, int b, int c){
    g[a].push_back(pii(b, c));
    g[b].push_back(pii(a, c));
}

void dfs(int u, int p, int d){
    depth[u] = d;
    par[0][u] = p;
    for(int i=0;i<g[u].size();i++){
        int v = g[u][i].first;
        if(v == p) continue;
        dfs(v, u, d+1);
    }
}

int LCA(int a, int b){
    if(depth[b] > depth[a]) swap(a, b);
    int diff = depth[a] - depth[b];
    for(int i=17;i>=0;i--) if((diff>>i)&1) a = par[i][a];
    if(a == b) return a;
    for(int i=17;i>=0;i--) if(par[i][a] != par[i][b]) a = par[i][a], b = par[i][b];
    return par[0][a];
}

int dist(int a, int b){
    return depth[a] + depth[b] - 2*depth[LCA(a, b)];
}

void cal_sz(int u, int p){
    sub[u] = 1;
    nn++;
    for(int i=0;i<g[u].size();i++){
        int v = g[u][i].first;
        if(v == p || vis[v]) continue;
        cal_sz(v, u);
        sub[u] += sub[v];
    }
}

int find_centroid(int u, int p){
    for(int i=0;i<g[u].size();i++){
        int v = g[u][i].first;
        if(v == p || vis[v]) continue;
        if(sub[v] > nn/2) return find_centroid(v, u);
    }
    return u;
}

int ft[N+5];
void update(int i, int v){
    for(;i<=N;i+=(i&-i)) ft[i]+=v;
}
int query(int i){
    int result = 0;
    for(;i>0;i-=(i&-i)) result+=ft[i];
    return result;
}

vector<pli> check1, add;
void dfs2(int u, int p, LL full, LL mn){
    check1.push_back(pli(mn, u));
    if(mn >= 0) ans++;
    for(int i=0;i<g[u].size();i++){
        int v = g[u][i].first, w = g[u][i].second;
        if(v == p || vis[v]) continue;
        dfs2(v, u, full+A[u]-w, min(mn, full+A[u]-w));
    }
}

vector<int> check2;
LL dp[N+5];
void dfs3(int u, int p, LL val, LL go, LL full, LL mn){
    dp[u] = go;
    add.push_back(pli(mn, u));
    if(val >= 0) check2.push_back(u);
    for(int i=0;i<g[u].size();i++){
        int v = g[u][i].first, w = g[u][i].second;
        if(v == p || vis[v]) continue;
        dfs3(v, u, min(val+A[v]-w, (LL)A[v]-w), go+A[v]-w, full+A[u]-w, min(mn, full+A[u]-w));
    }
}

void decompose(int u, int p){
    nn = 0;
    cal_sz(u, 0);
    int centroid = find_centroid(u, 0);
    vis[centroid] = 1;
    par2[centroid] = p;

    check1.clear(), check2.clear();
    check1.push_back(pli(-1e18, 0));
    LL full = A[centroid];

    for(int i=0;i<g[centroid].size();i++){
        int v = g[centroid][i].first, w = g[centroid][i].second;
        if(v == p || vis[v]) continue;
        dfs2(v, centroid, full-w, full-w);
    }

    sort(check1.begin(), check1.end());
    for(int i=1;i<check1.size();i++) update(i, 1);
    for(int i=0;i<g[centroid].size();i++){
        int v = g[centroid][i].first, w = g[centroid][i].second;
        if(v == p || vis[v]) continue;
        check2.clear(), add.clear();
        dfs3(v, centroid, A[v]-w, A[v]-w, full-w, full-w);
        ans += check2.size();
        for(int j=0;j<add.size();j++){
            int k = lower_bound(check1.begin(), check1.end(), add[j]) - check1.begin();
            update(k, -1);
        }
        for(int j=0;j<check2.size();j++){
            int k = check2[j];
            int l = lower_bound(check1.begin(), check1.end(), pli(-dp[k], 0)) - check1.begin();
            ans += query(N) - query(l-1);
        }
        for(int j=0;j<add.size();j++){
            int k = lower_bound(check1.begin(), check1.end(), add[j]) - check1.begin();
            update(k, 1);
        }
    }
    for(int i=1;i<check1.size();i++) update(i, -1);

    for(int i=0;i<g[centroid].size();i++){
        int v = g[centroid][i].first;
        if(v == p || vis[v]) continue;
        decompose(v, centroid);
    }

}

void getParent(){
    for(int j=1;j<17;j++){
        for(int i=1;i<=n;i++){
            if(par[j-1][i] != 0) par[j][i] = par[j-1][par[j-1][i]];
        }
    }
}

int main(){
    int n;
    scanf("%d", &n);
    for(int i=1;i<=n;i++) scanf("%d", &A[i]);
    init(n);
    for(int i=2;i<=n;i++){
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        addEdge(a, b, c);
    }
    dfs(1, 0, 0);
    getParent();
    decompose(1, 0);
    printf("%lld\n", ans);
}

Compilation message

transport.cpp: In function 'void dfs(int, int, int)':
transport.cpp:58:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[u].size();i++){
                 ~^~~~~~~~~~~~
transport.cpp: In function 'void cal_sz(int, int)':
transport.cpp:81:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[u].size();i++){
                 ~^~~~~~~~~~~~
transport.cpp: In function 'int find_centroid(int, int)':
transport.cpp:90:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[u].size();i++){
                 ~^~~~~~~~~~~~
transport.cpp: In function 'void dfs2(int, int, LL, LL)':
transport.cpp:112:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[u].size();i++){
                 ~^~~~~~~~~~~~
transport.cpp: In function 'void dfs3(int, int, LL, LL, LL, LL)':
transport.cpp:125:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[u].size();i++){
                 ~^~~~~~~~~~~~
transport.cpp: In function 'void decompose(int, int)':
transport.cpp:143:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[centroid].size();i++){
                 ~^~~~~~~~~~~~~~~~~~~
transport.cpp:150:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=1;i<check1.size();i++) update(i, 1);
                 ~^~~~~~~~~~~~~~
transport.cpp:151:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[centroid].size();i++){
                 ~^~~~~~~~~~~~~~~~~~~
transport.cpp:157:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(int j=0;j<add.size();j++){
                     ~^~~~~~~~~~~
transport.cpp:161:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(int j=0;j<check2.size();j++){
                     ~^~~~~~~~~~~~~~
transport.cpp:166:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(int j=0;j<add.size();j++){
                     ~^~~~~~~~~~~
transport.cpp:171:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=1;i<check1.size();i++) update(i, -1);
                 ~^~~~~~~~~~~~~~
transport.cpp:173:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i=0;i<g[centroid].size();i++){
                 ~^~~~~~~~~~~~~~~~~~~
transport.cpp: In function 'int main()':
transport.cpp:191:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d", &n);
     ~~~~~^~~~~~~~~~
transport.cpp:192:32: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     for(int i=1;i<=n;i++) scanf("%d", &A[i]);
                           ~~~~~^~~~~~~~~~~~~
transport.cpp:196:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d%d%d", &a, &b, &c);
         ~~~~~^~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 3320 KB Output is correct
2 Correct 17 ms 3448 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 18 ms 3704 KB Output is correct
2 Correct 22 ms 3960 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 199 ms 12816 KB Output is correct
2 Correct 180 ms 11756 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 286 ms 16256 KB Output is correct
2 Correct 325 ms 18288 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 402 ms 21352 KB Output is correct
2 Correct 505 ms 25336 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 134 ms 7280 KB Output is correct
2 Correct 70 ms 6904 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 122 ms 10348 KB Output is correct
2 Correct 214 ms 9892 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 317 ms 12760 KB Output is correct
2 Correct 267 ms 13548 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 427 ms 16180 KB Output is correct
2 Correct 377 ms 16868 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 602 ms 19996 KB Output is correct
2 Correct 507 ms 18536 KB Output is correct