Submission #262366

#TimeUsernameProblemLanguageResultExecution timeMemory
262366KastandaHarvest (JOI20_harvest)C++11
100 / 100
2052 ms252280 KiB
// M
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
template < typename T >
using ordered_set = tree < T , null_type , less < T > , rb_tree_tag , tree_order_statistics_node_update >;
typedef long long ll;
const int N = 200195;
int n, m, q, L, regenC, FNL, ts, A[N], B[N], M[N], Nxt[N];
ll T[N], RS[N], Lnxt[N], lz[N], D[N], F[N];
vector < int > Q[N], In[N], V[N];
vector < pair < ll , int > > VST[N];
ordered_set < pair < ll , int > > ST[N], TS[N];
void DFS(int v)
{
        M[v] = 1;
        for (int u : In[v])
        {
                if (!M[u])
                        DFS(u);
                if (u == v)
                        continue;
                lz[u] += Lnxt[u];
                if (ST[v].size() < ST[u].size())
                        ST[v].swap(ST[u]), swap(lz[v], lz[u]);
                for (auto a : ST[u])
                        ST[v].insert(make_pair(a.first + lz[u] - lz[v], a.second));
                ST[u].clear(); lz[u] = 0;
        }
        for (auto a : VST[v])
                ST[v].insert(make_pair(a.first - lz[v], a.second));
        for (int i : Q[v])
                RS[i] += ST[v].order_of_key({T[i] - lz[v], N});
}
inline void AddFen(int i, ll val)
{
        for (i ++; i < FNL; i += i & - i)
                F[i] += val;
}
inline ll GetFen(int i)
{
        ll rt = 0;
        for (i ++; i; i -= i & - i)
                rt += F[i];
        return rt;
}
inline void AddRem(int i, ll val)
{
        for (i ++; i < FNL; i += i & - i)
                TS[i].insert({val, ts ++});
}
inline ll GetRem(int i, ll le, ll ri)
{
        ll rt = 0;
        for (i ++; i; i -= i & - i)
                rt += TS[i].order_of_key({ri, -1}) - TS[i].order_of_key({le, -1});
        return rt;
}
int main()
{
        scanf("%d%d%d%d", &n, &m, &L, &regenC);
        for (int i = 1; i <= n; i ++)
                scanf("%d", &A[i]);
        for (int i = 1; i <= m; i ++)
                scanf("%d", &B[i]);
        scanf("%d", &q);
        for (int i = 1; i <= q; i ++)
        {
                int v;
                scanf("%d%lld", &v, &T[i]);
                Q[v].push_back(i);
        }

        // Building function graph ...
        for (int i = 1; i <= n; i ++)
        {
                ll c = regenC / L;
                ll r = regenC % L;
                Lnxt[i] += (ll)c * L;
                if (A[1] <= A[i] - r)
                        Nxt[i] = upper_bound(A + 1, A + n + 1, A[i] - r) - A - 1, Lnxt[i] += A[i] - A[Nxt[i]];
                else
                        Nxt[i] = upper_bound(A + 1, A + n + 1, A[i] - r + L) - A - 1, Lnxt[i] += L + A[i] - A[Nxt[i]];
        }
        for (int i = 1, ptr = 1; i <= m; i ++)
        {
                if (B[i] < A[1])
                        VST[n].push_back({B[i] + L - A[n], i});
                else
                {
                        while (ptr < n && A[ptr + 1] <= B[i])
                                ptr ++;
                        VST[ptr].push_back({B[i] - A[ptr], i});
                }
        }
        for (int i = 1; i <= n; i ++)
                In[Nxt[i]].push_back(i);
        for (int i = 1; i <= n; i ++)
                if (!M[i])
                        DFS(i);
        for (int i = 1; i <= n; i ++)
                if (ST[i].size()) // Head of a circle
                {
                        vector < int > C = {i};
                        int nw = Nxt[i];
                        while (nw != i)
                                C.push_back(nw), nw = Nxt[nw];
                        int k = (int)C.size();
                        C.push_back(i);
                        vector < ll > vec;
                        for (auto a : ST[i])
                                vec.push_back(a.first + lz[i]);
                        sort(vec.begin(), vec.end()); // Redundant
                        FNL = max((int)vec.size(), k) + 10;
                        D[0] = 0;
                        for (int j = 1; j <= k; j ++)
                                D[j] = D[j - 1] + Lnxt[C[j - 1]];
                        ll CL = D[k];
                        for (int j = 0; j < (int)vec.size(); j ++)
                        {
                                AddFen(j, vec[j] / CL);
                                AddRem(j, vec[j] % CL);
                                int lb = lower_bound(D + 1, D + k + 1, CL - vec[j] % CL) - D;
                                assert(lb <= k);
                                V[lb].push_back(j);
                        }
                        for (int j = 1; j <= k; j ++)
                        {
                                for (int id : V[j])
                                        AddFen(id, 1LL);

                                for (int id : Q[C[j]])
                                {
                                        int lb = upper_bound(vec.begin(), vec.end(), T[id] - D[j]) - vec.begin();
                                        RS[id] += (T[id] / CL) * (ll)lb;
                                        RS[id] -= GetFen(lb - 1);

                                        ll le = 0, ri = T[id] % CL;
                                        le = (le - D[j] % CL + CL) % CL;
                                        ri = (ri - D[j] % CL + CL) % CL;
                                        ri ++;

                                        if (le < ri)
                                                RS[id] += GetRem(lb - 1, le, ri);
                                        else
                                                RS[id] += GetRem(lb - 1, 0, ri) + GetRem(lb - 1, le, CL);
                                }
                        }

                        for (int j = 0; j <= FNL; j ++)
                        {
                                ts = 0;
                                F[j] = D[j] = 0;
                                TS[j].clear();
                                V[j].clear();
                        }
                }
        for (int i = 1; i <= q; i ++)
                printf("%lld\n", RS[i]);
        return 0;
}

Compilation message (stderr)

harvest.cpp: In function 'int main()':
harvest.cpp:63:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   63 |         scanf("%d%d%d%d", &n, &m, &L, &regenC);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
harvest.cpp:65:22: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   65 |                 scanf("%d", &A[i]);
      |                 ~~~~~^~~~~~~~~~~~~
harvest.cpp:67:22: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   67 |                 scanf("%d", &B[i]);
      |                 ~~~~~^~~~~~~~~~~~~
harvest.cpp:68:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   68 |         scanf("%d", &q);
      |         ~~~~~^~~~~~~~~~
harvest.cpp:72:22: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   72 |                 scanf("%d%lld", &v, &T[i]);
      |                 ~~~~~^~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...