Submission #1308085

#TimeUsernameProblemLanguageResultExecution timeMemory
1308085thnhannTwo Currencies (JOI23_currencies)C++20
100 / 100
1814 ms63580 KiB
//#pragma GCC optimize("Ofast,unroll-loops")
//#pragma GCC target("avx,avx2,fma,lzcnt,popcnt")
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define ii pair<int,int>
#define ill pair<ll,ll>
#define el cout<<'\n'
#define int long long

const ll mod=1e9+7;
const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
const int nmax=1e5;
const int inf =2e9;

void add(int &a, int b) {
    a += b;
    if (a >= mod) a -= mod;
    if (a < 0) a += mod;
}

template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}

using namespace std;

mt19937 rd(chrono::steady_clock::now().time_since_epoch().count());
int rand(int l, int r)
{
    return uniform_int_distribution<int>(l, r) (rd);
}

int n,m;
int q;
ii cost[nmax + 5];
vector<int>adj[nmax + 5];
ii edge[nmax + 5];

int h[nmax + 5];
int par[nmax + 5][23];

int in[nmax + 5];
int out[nmax + 5];
int timer = 0;

void dfs(int u,int dad)
{
    in[u] = ++timer;
    for(auto v:adj[u])
    {
        if(v == dad) continue;
        par[v][0] = u;
        h[v] = h[u] + 1;
        dfs(v,u);
    }
    out[u] = timer;
}

void prepare()
{
    for(int i=1;i<=19;i++)
        for(int j=1;j<=n;j++)
            par[j][i] = par[par[j][i - 1]][i - 1];
}

int LCA(int u,int v)
{
    if(h[v] > h[u])
        swap(u,v);
    for(int i=19;i>=0;i--)
    {
        if(h[par[u][i]] >= h[v])
            u = par[u][i];
    }
    if(u == v) return u;
    for(int i=19;i>=0;i--)
        if(par[u][i] != par[v][i])
    {
        u = par[u][i];
        v = par[v][i];
    }
    return par[u][0];
}

struct infor{
    int s,t,x,y;
}citizen[nmax + 5];

struct parallel{
    int L,R,ANS;
} ans[nmax + 5];


int fen_val[nmax + 5];
int fen_cnt[nmax + 5];
void update(int *bit, int idx, int val)
{
    while(idx <= n)
    {
        bit[idx] += val;
        idx += (idx&(-idx));
    }
}

void updaterange(int *bit, int L,int R,int val)
{
    update(bit, L,val);
    update(bit, R + 1,-val);
}

int get(int *bit, int idx)
{
    int res = 0;
    while(idx)
    {
        res += bit[idx];
        idx -= (idx&(-idx));
    }
    return res;
}

int get_path(int *bit, int u, int v, int lca) {
    return get(bit, in[u]) + get(bit, in[v]) - 2 * get(bit, in[lca]);
}

signed main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);cout.tie(0);
    cin >> n >> m >> q;

   for(int i=1;i<n;i++)
   {
        int u,v;
        cin >> u >> v;
        adj[u].pb(v);
        adj[v].pb(u);
        edge[i].fi = u;
        edge[i].se = v;
   }
   dfs(1,-1);
   prepare();

   for(int i=1;i<=m;i++)
   {
       cin >> cost[i].se >> cost[i].fi;
   }
   sort(cost + 1,cost + 1 + m);

   for(int i=1;i<=q;i++)
   {
       cin >> citizen[i].s >> citizen[i].t >> citizen[i].x >> citizen[i].y;
   }

   for(int i=1;i<=q;i++)
   {
       ans[i].L = 0;
       ans[i].R = m;
       ans[i].ANS = 0;
   }

    vector<int>bucket[nmax + 5];

    while(true)
    {
       bool has_query = false;
       for(int i=0; i<=m; i++) bucket[i].clear();

       for(int i=1;i<=q;i++)
       {
           if(ans[i].L <= ans[i].R)
           {
               has_query = true;
               int mid = (ans[i].L + ans[i].R) >> 1;
               bucket[mid].pb(i);
           }
       }

       if(!has_query) break;

       for(int i=0;i<=n;i++) {
           fen_val[i] = 0;
           fen_cnt[i] = 0;
       }

       for(auto j : bucket[0]) {
           ans[j].ANS = 0;
           ans[j].L = 1;
       }

       for(int i=1;i<=m;i++)
       {
           int u = edge[cost[i].se].fi;
           int v = edge[cost[i].se].se;
           if(par[u][0] == v) swap(u,v);
           updaterange(fen_val, in[v], out[v], cost[i].fi);
           updaterange(fen_cnt, in[v], out[v], 1);

           for(auto j:bucket[i])
           {
               int s = citizen[j].s;
               int t = citizen[j].t;
               int lca = LCA(s, t);

               int sliver = citizen[j].y;
               int need = get_path(fen_val, s, t, lca);
               int checkpoint = get_path(fen_cnt, s, t, lca);

               if(sliver >= need)
               {
                   ans[j].ANS = checkpoint;
                   ans[j].L = i + 1;
               }
               else
                   ans[j].R = i - 1;
                // cout << ans[j].L << " " << ans[j].R << " " << ans[j].ANS;el;
           }

       }
    }
    for(int i=0;i<=n;i++) fen_cnt[i] = 0;
    for(int i=1;i<=m;i++)
    {
        int u = edge[cost[i].se].fi;
        int v = edge[cost[i].se].se;
        if(par[u][0] == v) swap(u,v);
        updaterange(fen_cnt, in[v], out[v], 1);
    }

    for(int i=1;i<=q;i++)
    {
        int s = citizen[i].s;
        int t = citizen[i].t;

        int total = get_path(fen_cnt, s, t, LCA(s, t));
        int gold_needed = total - ans[i].ANS;
//        cout << total << " " << gold_needed << " " << citizen[i].x;el;
        if(citizen[i].x - gold_needed >= 0)
            cout << citizen[i].x - gold_needed;
        else cout << -1;
        el;
    }
}
//Can i get a kiss? And can u make it last forever?
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...