Submission #1014760

#TimeUsernameProblemLanguageResultExecution timeMemory
1014760alexddTwo Currencies (JOI23_currencies)C++17
100 / 100
544 ms47900 KiB
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 1e18;
int n,m,q;

int aib[100005][2];
int qry(int p, int c)
{
    int aux=0;
    for(int i=p;i>0;i-=(i&(-i)))
        aux += aib[i][c];
    return aux;
}
void upd(int p, int val, int c)
{
    for(int i=p;i<=n;i+=(i&(-i)))
        aib[i][c] += val;
}

vector<int> con[100005];
pair<int,int> edges[100005];
int tin[100005],tout[100005],timer;
int parent[100005];
vector<pair<int,int>> obstacole;
pair<int,int> drum[100005],bani[100005];
int lc[100005];
int anc[100005][17];
int rez[100005];
void dfs_init(int nod)
{
    tin[nod]=++timer;
    for(auto adj:con[nod])
    {
        if(adj!=parent[nod])
        {
            parent[adj]=nod;
            dfs_init(adj);
        }
    }
    tout[nod]=timer;
}
bool isanc(int x, int y)
{
    return (tin[x]<=tin[y] && tout[x]>=tout[y]);
}
int lca(int x, int y)
{
    if(isanc(x,y))
        return x;
    if(isanc(y,x))
        return y;
    for(int p=16;p>=0;p--)
        if(!isanc(anc[x][p],y))
            x = anc[x][p];
    return anc[x][0];
}
int poz;
void cautare_binara(int st, int dr, vector<int> ids)
{
    if(st>dr || ids.empty())
        return;
    int mij=(st+dr)/2;
    while(poz<mij)
    {
        poz++;
        upd(tin[obstacole[poz].second], obstacole[poz].first, 0);
        upd(tout[obstacole[poz].second]+1, -obstacole[poz].first, 0);

        upd(tin[obstacole[poz].second], -1, 1);
        upd(tout[obstacole[poz].second]+1, +1, 1);
    }
    while(poz>mij)
    {
        upd(tin[obstacole[poz].second], -obstacole[poz].first, 0);
        upd(tout[obstacole[poz].second]+1, obstacole[poz].first, 0);

        upd(tin[obstacole[poz].second], +1, 1);
        upd(tout[obstacole[poz].second]+1, -1, 1);
        poz--;
    }
    vector<int> tole,tori;
    for(auto x:ids)
    {
        int aux0 = qry(tin[drum[x].first],0) + qry(tin[drum[x].second],0) - 2*qry(tin[lc[x]],0);
        int aux1 = qry(tin[drum[x].first],1) + qry(tin[drum[x].second],1) - 2*qry(tin[lc[x]],1);
        //cout<<aux0<<" aux0\n";
        if(aux0 <= bani[x].second)
        {
            rez[x] = min(rez[x], aux1);
            tori.push_back(x);
        }
        else
            tole.push_back(x);
    }
    if(st<dr)
    {
        cautare_binara(st,mij,tole);
        cautare_binara(mij+1,dr,tori);
    }
}
signed main()
{
    cin>>n>>m>>q;
    int a,b;
    for(int i=1;i<n;i++)
    {
        cin>>a>>b;
        edges[i] = {a,b};
        con[a].push_back(b);
        con[b].push_back(a);
    }
    dfs_init(1);
    for(int i=1;i<n;i++)
        if(parent[edges[i].first]==edges[i].second)
            swap(edges[i].first, edges[i].second);

    for(int i=1;i<=n;i++)
        anc[i][0]=parent[i];
    anc[1][0]=1;
    for(int p=1;p<17;p++)
        for(int i=1;i<=n;i++)
            anc[i][p] = anc[anc[i][p-1]][p-1];

    for(int i=1;i<=m;i++)
    {
        cin>>a>>b;
        obstacole.push_back({b,edges[a].second});
        upd(tin[edges[a].second], +1, 1);
        upd(tout[edges[a].second]+1, -1, 1);
    }
    sort(obstacole.begin(),obstacole.end());
    vector<int> ids;
    for(int i=1;i<=q;i++)
    {
        cin>>drum[i].first>>drum[i].second>>bani[i].first>>bani[i].second;
        lc[i] = lca(drum[i].first, drum[i].second);
        ids.push_back(i);
        rez[i] = qry(tin[drum[i].first],1) + qry(tin[drum[i].second],1) - 2*qry(tin[lc[i]],1);
    }
    poz=-1;
    cautare_binara(0,m-1,ids);
    for(int i=1;i<=q;i++)
    {
        if(rez[i] > bani[i].first)
            cout<<-1<<"\n";
        else
            cout<<bani[i].first-rez[i]<<"\n";
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...