結果

問題 No.1891 Static Xor Range Composite Query
ユーザー vjudge1
提出日時 2025-08-31 21:13:50
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 4,561 bytes
コンパイル時間 3,293 ms
コンパイル使用メモリ 286,084 KB
実行使用メモリ 15,944 KB
最終ジャッジ日時 2025-08-31 21:14:01
合計ジャッジ時間 11,717 ms
ジャッジサーバーID
(参考情報)
judge4 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 20 TLE * 1 -- * 9
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;

void PRE() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    freopen("error.txt", "w", stderr);
#endif
}
const int mod = 998244353;
/*
 * This segment tree is like normal segment tree but in query you query on position x ^ i for all l <= i <= r
 * you only need to handle apply and merge
 * you must pass n to be power of 2 and when build pad the vector with zeros until it's length be power of 2
*/

const ll inf = 1e18;
struct Node {
    ll a , b;
    Node(ll x = 1 , ll y = 0) {
        a = x , b = y;
    }
    Node operator+(const Node &other) {
        // x * a + b , other.a * x + other.b
        // other.a * (x * a + b) + other.b
        return Node(other.a * a % mod , (other.a * b + other.b) % mod);
    }

};
template<typename T>
struct Seg {
    ll apply(ll old , ll nw) {
        // apply update to certain leaf node
        return old ^ nw;
    }

    T merge(T l , T r) {
        // merge answer
        return l + r;
    }

    int n;
    int N;
    int LOG;
    vector<vector<T>> t;

    Seg(int n = 0) {
        if (n > 0) init(n);
    }

    void init(int _n) {
        n = _n;
        LOG = 0;
        while ((1 << LOG) < n) ++LOG;
        N = 1 << LOG;
        t.assign(4 * N + 5, {});
    }

    vector<T> mergeNode(const vector<T>& L, const vector<T>& R) {
        // merge 2
        int half = (int)L.size();
        vector<T> res(half * 2);
        for (int i = 0; i < half; ++i) res[i] = merge(L[i] , R[i]);
        for (int i = 0; i < half; ++i) res[i + half] = merge(R[i] , L[i]);
        return res;
    }

    void build(int node, int b, int e, const vector<T>& a) {
        if (b == e) {
            t[node].assign(1, (b < (int)a.size() ? a[b] : 0LL));
            return;
        }
        int mid = (b + e) >> 1;
        int L = node << 1, R = L | 1;
        build(L, b, mid, a);
        build(R, mid + 1, e, a);
        t[node] = mergeNode(t[L], t[R]);
    }

    // point update: A[idx] ^= val
    void update_xor(int node, int b, int e, int idx, ll val) {
        if (idx < b || idx > e) return;
        if (b == e) {
            t[node][0] = apply(t[node][0] , val);
            return;
        }
        int mid = (b + e) >> 1;
        int L = node << 1, R = L | 1;
        update_xor(L, b, mid, idx, val);
        update_xor(R, mid + 1, e, idx, val);
        t[node] = mergeNode(t[L], t[R]);
    }

    // query: XOR of A[p ^ x] for p in [i..j]
    T query(int node, int b, int e, int i, int j, int x, int layer = -2) {
        if (i > j || b > j || e < i) return Node();
        if (layer == -2) layer = LOG - 1;

        if (i <= b && e <= j) {
            if (layer == -1) return t[node][0];
            int mask = (1 << (layer + 1)) - 1;
            int idx = x & mask;
            if (idx >= (int)t[node].size()) idx %= (int)t[node].size();
            return t[node][idx];
        }

        int mid = (b + e) >> 1;
        int L = node << 1, R = L | 1;

        // check bit 'layer' of x: if 0 -> normal mapping, else swapped mapping
        if (((~x) >> layer) & 1) {
            return merge(query(L, b, mid, i, j, x, layer - 1)  , query(R, mid + 1, e, i, j, x, layer - 1));
        } else {
            // swapped: left part queries map into right subtree and vice versa
            T res = 0;
            int i1 = i, j1 = min(mid, j);
            int i2 = max(i, mid + 1), j2 = j;

            if (i1 <= j1) {
                int ni = mid + 1 + (i1 - b);
                int nj = mid + 1 + (j1 - b);
                res = merge(res , query(R, mid + 1, e, ni, nj, x, layer - 1));
            }
            if (i2 <= j2) {
                int ni = b + (i2 - (mid + 1));
                int nj = b + (j2 - (mid + 1));
                res = merge(res  ,query(L, b, mid, ni, nj, x, layer - 1));
            }
            return res;
        }
    }
};


int main() {
    PRE();
    int n , q;cin >> n >> q;
    int N = 1;
    while (N < n) N <<= 1;
    vector<Node> v(N);
    for (int i = 0;i < n;i++) cin >> v[i].a >> v[i].b;
    Seg<Node> seg(N);
    seg.build(0 , 0 , N - 1 , v);
    for (int i = 0;i < q;i++) {
        int l , r , p , x;
        cin >> l >> r >> p >> x;
        r--;
        // auto res = seg.query(0 , 0 , N - 1 , l , r , p);
        Node res;
        for (int j = l;j <= r;j++) res = res + v[j ^ p];
        // coout <<
        cout << (res.a * x + res.b) % mod << '\n';
    }
}
0