P3203 [HNOI2010] Blocking

Title

Portal P3203 [HNOI2010] Bouncing Sheep

answer

F [ i ] F[i] F [ i ] represents fromiiThe number of bombs from the position i to the fly, then there is a recurrenceF [i] = F [i + ki] + 1 F[i]=F[i+k_i]+1F[i]=F[i+ki]+1 . Modify any positioniii capital possible oppositej (j <i) j (j <i)j ( j<The position of i ) has an impact, and there are two naive approaches:O (N) O(N)O ( N ) to modify,O (1) O(1)O ( 1 ) to query;O (1) O (1)O ( 1 ) to modify,O (N) O(N)O ( N ) to query. Need to balance the complexity of modification and query.

Consider blocking, nxt [i] nxt[i]n x t [ i ] Representative positioniii jumps out of the first position of the block,F [i] F[i]F [ i ] Representativeiii tonxt [i] nxt [i]n x t [ i ] The number of bombs. ThenO (N) O(\sqrt N)O (N ) Violent reconstruction of the block where the modified position is located,O (N) O(\sqrt N)O (N ) Query. Total time complexityO (MN) O(M\sqrt N)O ( MN )

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200005, maxq = 1005;
int N, M, A[maxn];
int tot, L[maxq], R[maxq], id[maxn], nxt[maxn], F[maxn];

void change(int l, int x)
{
    
    
    A[l] = x;
    int p = id[l];
    for (int i = R[p]; i >= L[p]; --i)
        if (i + A[i] > R[p])
            nxt[i] = i + A[i], F[i] = 1;
        else
            nxt[i] = nxt[i + A[i]], F[i] = F[i + A[i]] + 1;
}

int ask(int l)
{
    
    
    int res = 0;
    while (l <= N)
        res += F[l], l = nxt[l];
    return res;
}

int main()
{
    
    
    scanf("%d", &N);
    for (int i = 1; i <= N; ++i)
        scanf("%d", A + i);
    int w = sqrt(N);
    for (int i = 1; i <= N; i += w)
        L[++tot] = i, R[tot] = min(N, i + w - 1);
    for (int i = 1; i <= tot; ++i)
        for (int j = L[i]; j <= R[i]; ++j)
            id[j] = i;
    for (int i = N; i; --i)
        if (i + A[i] > R[id[i]])
            nxt[i] = i + A[i], F[i] = 1;
        else
            nxt[i] = nxt[i + A[i]], F[i] = F[i + A[i]] + 1;
    scanf("%d", &M);
    while (M--)
    {
    
    
        int i, j, k;
        scanf("%d%d", &i, &j);
        ++j;
        if (i == 1)
            printf("%d\n", ask(j));
        else
            scanf("%d", &k), change(j, k);
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/neweryyy/article/details/114801857