LOJ (510) : "LibreOJ NOI 라운드 # 1"북한이 학교의 추억 외부

주제 포털 : LOJ # 510 .

질문의 의미를 설명 :

주어진에서 \ (K \) 16 진수 펜윅 나무, 그러나 그것의 구현 문제입니다.

그래서 상기 정식 \ (\ mathrm lowbit {} ( x)는 \) 와 같은 \ (K \) 진수에서 \ (X \) 최저 비 - 제로 비트 값, 예를 들면, \ (\ mathrm {} lowbit \! \ 좌회전 (230 _ {. (5)} \ 오른쪽)! \ _ = {(30). (5)} \) .

add(x, v)동작이 수행된다
\ (X \ 르 n \) , 실행 s[x] ^= v\ (X는 \) 된다 \ (X + \ mathrm lowbit} {(X) \) 및 사이클이 계속.

query(x)동작이 수행된다 :
주문 \ (ANS \) 의 초기 값 (\ 0 \) .
경우 \ (x> 0 \) , 실행 ans ^= s[x]\ (X \) 된다 \ (X - \ mathrm lowbit} {(X) \) 와주기를 계속한다.
결국 반환 (ANS \) \ .

해결 방법 :

올바르게 기록과 달리, add연산의 수는 동작하지 않는 동안 수행 \ (\는 O (K \ mathcal log_K N)는 \) 하지만 \ (\ mathcal O (N) \) 관찰 복잡도가 발생할 때 변화율 : (K = 3, X = 1 \) \ 시간, \ (X는 \) (10 진수)로 변경 \ (1 \ 2 \ 4를 \로 5 \ 7을 \ 8을 \ (10)..... \에 \ cdots \) .

찾을 수 \ (X 축 \) 에서 \ (K \) 이진 최저 비 - 제로 비트 위치는 그대로 유지하고, (A) 내로 비트들의 가장 아닌 값 \ (1, 2, 1, 2, \ ldots 단락 \ ) 주기.

다른 들어 \ (K \) , 우리가 지정된 최소 비 제로 비트의 값의 변화를 관찰, 일부는 결국로 바뀌 찾을 \ (0 \) , 더 이상 제로입니다, 다른 사람들이 가을 동안 루프.

분명히, 이것은 실제로 함수 \ (F (X) = 2 × \ BMOD K \) 성분 접속 루트 포리스트 내 고리이며 해당 그래프에 전사 공정 \ (0 \ 0 \)로 링에서와 \ (0 \) 결국 비 숫자 0을 향상시키는 가장 낮은 지점에 접속된다.

번호 이론은 나무 링 내에서 그들 각각의 깊이가 초과하지 않습니다라고 우리에게 이야기한다 \ (\ log_2 K \) , 루트 인 경우 어디 \ (0 \) 트리, 가장 낮은 수준 만 변경됩니다 내에서 기본 링 (\ \ log_K N \) 의 총 번호, \ (\ log_2 K \ 번 \ log_K N- 형 = \ log_2 \ N- 형) 는 폭력이 부분을 건너 뛸 수 있습니다.

경우 마지막 그렇지 떨어 \ (0 \) 위의 예를 참조하여 고리는, 후방으로 연장하는 무한 체인을 형성하는 것이지만,이 체인의 루프 부분의 인접한 위치들 사이의 차이 인 경우.
각 체인의 사전 아웃 경우, 각 체인이 접미사, 하나 열거 작동을 유지하기위한 트리 배열을 시작할 수 있습니다.
그러나,이 범위를 너무 크게하는 전처리 직접 때문에 쇄, 즉 직접 결정된 소수점 수를 승산하는 방법을 고려할 것이다 \ (X를 \) 에 첫 번째로, 현재 위치에서 여러 사슬이고, 될 수 직접적 펜윅 트리 동작 (물론,이 시간 범위는 여전히 매우 중요하지만, 위치의 변화의 해시에 의해 작은 배열에 매핑된다).

같은 토큰을 물었을 때 query\ (X \) 으로 변경됩니다 \ (\ log_K N \) 먼저 결정, 조사를 지시 할 수 있도록 시간, 때마다 (X \) \ 체인에 직접 수정하지 않을 경우, (\ ANS \)가 필요하거나 차이가 프리픽스 체크 첨가하는 단일 지점이 될 수있는 것으로) 접미사 개정 대응 전의 동작 (단일 쇄 열거 따른 전류 펜윅 트리되도록하려면 고전 해시 넓은 범위의 이입 방법에 대한 펜윅 트리 동작.

다음 코드는 해시의 시간 복잡도를 가정한다 \ (\ mathcal O. (1) \) 후 총 시간 복잡도이다 \ (\ mathcal O (K \ 로그 N + Q \ log_K n \) N 기록 \) :

#include <cstdio>

const int HASH = 19260817, NUMS = 10000005;
int h[HASH], nxt[NUMS], to[NUMS], tot;
inline int Hasher(int val, int typ) {
    int cyp = (val ^ val >> 1) % HASH;
    for (int i = h[cyp]; i; i = nxt[i]) if (to[i] == val) return i;
    return typ ? nxt[++tot] = h[cyp], to[tot] = val, h[cyp] = tot : 0;
}

typedef long long LL;
const int MK = 200005;

int N, K, Q, V[6], C;
inline void lowbit(int x, int &y, int &z) {
    int s = 1, t = C;
    while (t) { if (x % V[t] == 0) x /= V[t], s *= V[t]; --t; }
    y = x % K, z = y * s;
}
int ltrs[MK][30], ntrs[MK][30];
LL lsum[MK][30], nsum[MK][30];
int arr[NUMS];

int main() {
    scanf("%d%d%d", &N, &Q, &K);
    for (LL x = K; x <= N; x *= x) V[++C] = x;
    for (int i = 1; i < K; ++i) if ((i & -i) >= (K & -K))
        ltrs[i * 2 % K][0] = lsum[i * 2 % K][0] = i,
        ntrs[i][0] = i * 2 % K, nsum[i][0] = i;
    for (int j = 0; j < 29; ++j)
        for (int i = 1; i < K; ++i) if ((i & -i) >= (K & -K))
            ltrs[i][j + 1] = ltrs[ltrs[i][j]][j],
            lsum[i][j + 1] = lsum[i][j] + lsum[ltrs[i][j]][j],
            ntrs[i][j + 1] = ntrs[ntrs[i][j]][j],
            nsum[i][j + 1] = nsum[i][j] + nsum[ntrs[i][j]][j];
    for (int i = 1; i <= Q; ++i) {
        int op, x, y, z, v, d;
        scanf("%d%d", &op, &x);
        if (op == 1) {
            scanf("%d", &v);
            while (x <= N) {
                lowbit(x, y, z);
                if ((y & -y) >= (K & -K)) {
                    int id = 0, X = x, Y = y, w = z / y;
                    for (int j = 29; j >= 0; --j)
                        if (lsum[Y][j] < X / w)
                            id |= 1 << j,
                            X -= lsum[Y][j] * w,
                            Y = ltrs[Y][j];
                    ++id;
                    for (int j = 0; x <= N; ++j) if (id >> j & 1) {
                        arr[Hasher(x, 1)] ^= v;
                        x += nsum[y][j] * w;
                        y = ntrs[y][j];
                        id += 1 << j;
                    }
                    break;
                }
                arr[Hasher(x, 1)] ^= v;
                x += z;
            }
        } else {
            int Ans = 0;
            while (x) {
                lowbit(x, y, z);
                if ((y & -y) >= (K & -K)) {
                    int id = 0, X = x, Y = y, w = z / y;
                    for (int j = 29; j >= 0; --j)
                        if (lsum[Y][j] < X / w)
                            id |= 1 << j,
                            X -= lsum[Y][j] * w,
                            Y = ltrs[Y][j];
                    ++id;
                    X = x, Y = y;
                    for (int j = 0; id; ++j, id >>= 1) if (id & 1) {
                        if ((d = Hasher(X, 0))) Ans ^= arr[d];
                        X -= lsum[Y][j] * w;
                        Y = ltrs[Y][j];
                    }
                } else if ((d = Hasher(x, 0))) Ans ^= arr[d];
                x -= z;
            }
            printf("%d\n", Ans);
        }
    }
    return 0;
}

추천

출처www.cnblogs.com/PinkRabbit/p/LOJ510.html