1. 程式人生 > 實用技巧 >linux--系統管理--使用者和使用者組管理

linux--系統管理--使用者和使用者組管理

\(\mathcal{Description:}\)

給定一個長度為 n 的序列 \(a_1, a_2, a_3, ..., a_n\), 每個數大小不超過 1000;

有 m 次操作,每次操作改變一個數的值,或求一段區間 [l, r] 的所有子區間的異或和之和。

多組資料。 每個操作第一個數是 opt

  • 當 opt 為 1 時,讀入 pos, val,表示修改第 pos 個數的值為 val。
  • 當 opt 為 2 時,讀入 l, r, 表示詢問 \(\sum_{l \leq i \leq j \leq r} \bigoplus_{i \leq k \leq j} a_k\)

\(\mathcal{Solution:}\)

\(\mathbb{Summary:}\)

線段樹分治入門題。因為直接做看起來沒什麼思路,數的範圍又在 1000 以內,考慮拆位算貢獻。

\(\text{Segmentree}_i\) 表示序列上數的第 i 位所構建的線段樹。

對於線段樹上每個點:

  • 定義 sum 為區間異或和。

  • l0、l1 表示區間內 從左到右連續的、異或和分別為 0、1 的子序列 個數。

    r0、r1 表示區間內 從右到左連續的、異或和分別為 0、1 的子序列 個數。

  • s0、s1 表示區間內 異或和分別為 0、1 的子序列 個數。

轉移也十分顯然:

\[\begin{aligned} & sum_p = sum_{ls} \oplus sum_{rs} \\ & l_{0, p} = l_{0,ls} + l_{sum_{ls}, rs}, \ \ \ \ \ \ l_{1, p} = l_{1, ls} + l_{sum_{ls} \oplus 1, rs} \\ & r_{0, p} = r_{0,rs} + r_{sum_{rs}, ls}, \ \ \ r_{1, p} = r_{1, rs} + r_{sum_{rs} \oplus 1, ls} \\ & s_{0, p} = s_{0, ls} + s_{0, rs} + l_{0, rs} r_{0, ls} + l_{1, rs} r_{1, ls} \\ & s_{1, p} = s_{1, ls} + s_{1, rs} + l_{1, rs} r_{0, ls} + l_{0, rs} r_{1, ls} \end{aligned} \]

根據異或運算的規律 相同則 0, 不同為 1,可以很好理解上述轉移式。

\(\mathbb{Detail:}\)

  • 空間比較緊,注意到 \(2^{10} = 1024 > 1000\),所以線段樹理論開 9 棵即可。

  • 注意模數為 4001

  • 也許可以定義一個類,這樣構造、修改、查詢都方便。

\(\mathbb{Code:}\)

#include <bits/stdc++.h>
#define Rep(i, a, b) for (int i = (a), bb = (b); i <= bb; ++i)
const int N = 1e5 + 5, mod = 4001;
using namespace std;
int n, m, a[N], t, ans;
char BB[1 << 15], *S = BB, *T = BB;
#define getchar() (S == T && (T = (S = BB) + fread(BB, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
inline int read() { 
    int s = 0; char c = getchar(); for (; !isdigit(c); c = getchar()); 
    for (; isdigit(c); c = getchar()) s = (s << 3) + (s << 1) + c - 48; return s; 
}
template <class K> inline void write(K x) { 
    (x > 9 ? write(x / 10) : void()); 
    return putchar(x % 10 + 48), void(); 
}
inline int add(int a, int b) { return a + b >= mod ? a + b - mod : a + b; } 
inline void Add(int &a, int b) { return a = add(a, b), void(); }
inline int mul(int a, int b) { return 1LL * a * b % mod; } 
inline void Mul(int &a, int b) { return a = mul(a, b), void(); }
struct Se_P { 
    int sum, s[2], l[2], r[2]; 
    inline void clear(){sum = 0; Rep(i, 0, 1) s[i] = l[i] = r[i] = 0;}
} Void;
struct Segmentree { 
    Se_P t[N << 2], s; int tmp;
    #define sum(p) t[p].sum
    #define ls (p << 1)
    #define rs (ls | 1)
    #define mid ((x + y) >> 1)
    #define Ls ls, x, mid
    #define Rs rs, mid + 1, y
    inline Se_P Spread(Se_P l, Se_P r) { s.clear();
        s.s[0] = add(add(add(l.s[0], r.s[0]), mul(l.r[0], r.l[0])), mul(l.r[1], r.l[1]));
        s.s[1] = add(add(add(l.s[1], r.s[1]), mul(l.r[0], r.l[1])), mul(l.r[1], r.l[0]));
        
        if (l.sum == 0) s.l[0] = l.l[0] + r.l[0], s.l[1] = l.l[1] + r.l[1];
        else s.l[0] = l.l[0] + r.l[1], s.l[1] = l.l[1] + r.l[0];
                                        
        if (r.sum == 0) s.r[0] = r.r[0] + l.r[0], s.r[1] = r.r[1] + l.r[1];
        else s.r[0] = r.r[0] + l.r[1], s.r[1] = r.r[1] + l.r[0];
                                        
        s.sum = l.sum ^ r.sum;
        return s;
    }
    inline void Push(int p) { return t[p] = Spread(t[ls], t[rs]), void(); }
    inline void Build(int p, int x, int y, int op) { 
        t[p].clear();
        if (x == y) { 
            tmp = (a[x] & (1 << op)) ? 1 : 0; 
            return t[p].l[tmp] = t[p].r[tmp] = t[p].s[tmp] = 1, sum(p) = tmp, void(); 
        }
        return Build(Ls, op), Build(Rs, op), Push(p);
    }
    inline void Modify(int p, int x, int y, int pos, int v) {
        if (x == y) return t[p].clear(), t[p].l[v] = t[p].r[v] = t[p].s[v] = 1, sum(p) = v, void();
        (pos <= mid ? Modify(Ls, pos, v) : Modify(Rs, pos, v)), Push(p);
    }
    inline Se_P Ask(int p, int x, int y, int l, int r) {
        if (l > r || x > y || x > r || l > y) return Void;
        if (l <= x && y <= r) return t[p];
        return Spread(Ask(Ls, l, r), Ask(Rs, l, r));
    }
} Se[10];
int main(void) {
    n = read(), m = read(), Void.clear();
    Rep(i, 1, n) a[i] = read();
    Rep(i, 0, 9) Se[i].Build(1, 1, n, i);
    Rep(i, 1, m) {
        int opt = read(), x = read(), y = read();
        if (opt == 1) { 
            Rep(i, 0, 9) Se[i].Modify(1, 1, n, x, (y & (1 << i)) ? 1 : 0); 
        }
        if (opt == 2) { 
            t = 1, ans = 0;
            Rep(i, 0, 9) Add(ans, mul(Se[i].Ask(1, 1, n, x, y).s[1], t)), Mul(t, 2);
            write(ans), putchar(10);
        }
    }
    return 0;
}