0%

不知不覺就到了最後一天上課了(明天會是五個小時的大團體賽),時間過真快。

今天上的東西都是屬於我不太熟悉的,所以感覺可以學到不少東西(前提是聽得懂)

閱讀全文 »

現在我要給你一個長度為$n$的數列,每一項初始值為$a_i$,$q$筆操作每筆操作有兩種。

一,給你L, R,請算出 [L,R] 的總和。
二,給你L, R, X,請把 [L,R] 中的所有數字都 XOR X。

$n\le 10^5, q\le 50000, a_i\le 10^6$


如果維護一顆線段樹,區間xor沒辦法直接地得出她對答案的影響(所以無法用懶標)。
但如果對於每個bit都維護一個線段樹呢?每顆線段樹都會只存01,而xor操作會變成區間反轉!
所以維護$\log a_i$科線段樹就好了。
複雜度$\mathcal{O}(N\log a_i\log N+Q\log a_i\log N)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
-------------- | /
| | /
| | /
| * |/ | | ------ *
| | | | / \
| | |\ | | | |\ |
\ | | | \ | | | | \ |
\ | | | \ | | \ / \ |
V | | \ \__/| ----- \ |
*/
#include <bits/stdc++.h>
using namespace std;

#define EmiliaMyWife ios::sync_with_stdio(0); cin.tie(NULL);
using ll = int64_t;
using ull = uint64_t;
using ld = long double;
using uint = uint32_t;
const double EPS = 1e-8;
const int INF = 0x3F3F3F3F;
const ll LINF = 4611686018427387903;
const int MOD = 1e9+7;
/*--------------------------------------------------------------------------------------*/

const int N = 1e5 + 25;
struct segtree {
int arr[N << 1], tag[N], n;
void init(int _n) { n = _n; }
void upd(int p, int h) {
arr[p] = (1 << h) - arr[p];
if(p < n)
tag[p] ^= 1;
}
void push(int p) {
for(int h = __lg(p); ~h; h--) {
int i = p >> h;
if(!tag[i >> 1])
continue;
upd(i, h);
upd(i ^ 1, h);
tag[i >> 1] = 0;
}
}
void pull(int p) {
for(int h = 1; p > 1; p >>= 1, h++) {
arr[p >> 1] = arr[p] + arr[p ^ 1];
if(tag[p >> 1])
arr[p >> 1] = (1 << h) - arr[p >> 1];
}
}
void edt(int l, int r) {
int tl = l, tr = r, h = 0;
push(tl + n); push(tr + n - 1);
for(l += n, r += n; l < r; l >>= 1, r >>= 1, h++) {
if(l & 1)
upd(l++, h);
if(r & 1)
upd(--r, h);
}
pull(tl + n); pull(tr + n - 1);
}
int que(int l, int r) {
int res = 0;
push(l + n); push(r + n - 1);
for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
if(l & 1)
res += arr[l++];
if(r & 1)
res += arr[--r];
}
return res;
}
} tree[20];

signed main() { EmiliaMyWife
int n;
cin >> n;
for(int j = 0; j < 20; j++)
tree[j].init(n);
for(int i = 0, x; i < n; i++) {
cin >> x;
for(int j = 0; j < 20; j++)
if(x >> j & 1)
tree[j].edt(i, i + 1);
}
int q;
cin >> q;
while(q--) {
int t;
cin >> t;
if(t == 1) {
int l, r;
cin >> l >> r;
ll res = 0;
for(int i = 0; i < 20; i++)
res += ll(tree[i].que(l - 1, r)) << i;
cout << res << '\n';
}
else {
int l, r, x;
cin >> l >> r >> x;
for(int i = 0; i < 20; i++)
if(x >> i & 1)
tree[i].edt(l - 1, r);
}
}
}

給一個$n\times m$的01矩陣,問有幾個正方形子矩陣滿足該子矩陣內的數字全都是1,並且輸出最長的邊長。

閱讀全文 »

傳說中,P教授擁有一個蹺蹺板,叫作P-蹺蹺板。P-蹺蹺板是個長直且質量可忽略的板子,上面有$N$個等距的座位,編號為$0$到$N-1$,每個座位都只能坐一個人。特別的是,P-蹺蹺板的支點並不是固定的,使用者可以將支點架在任何一個座位的正下方

如果支點左右的力矩相同,那麼蹺蹺板將會平衡。例如若$N=5$ ,五個座位上面的重量依序為$2,1,5,3,1$,若將支點架在$2$號座位下方,則左邊力矩$\ =2\times 2 + 1\times 1 = 3\times 1 + 1\times 2=\ $右邊力矩,故蹺蹺板會平衡。

閱讀全文 »

給一張$n$個點與$m$條邊的有向圖,再給一個數字$L$。

$Q$筆詢問,每筆詢問從$a$走到$b$且恰好經過$L$條邊(可重複)的路徑有幾條

閱讀全文 »

在寬度為n的照片中,總共有多少種不同的山稜線呢 ?

為了簡化問題,一段長度為n的山稜線將由許多寬度為1的片段構成。
同時在每個片段當中,山稜線不是45度斜向上就是45度斜向下。
當然,相鄰兩個片段的山稜線必須連續,而且山稜線的兩端必須貼齊地平線。
此外,山稜線的任何一部分都不能低於地平線(即照片底端)。

舉例來說,以下就是一個合法的山稜線:

閱讀全文 »