# Tsinghua 2018 DSA PA3简要题解

CST2018 3-1-1 Sum (15%)

CST2018 3-1-2 Max (20%)

  1 #include <cstdio>
2
3 using namespace std;
4 const int N = 5e5 + 5;
5 const int inf = 1e9;
6 int n, m;
7 int a[N];
8
9 inline int max(int x, int y) {
10     return x > y ? x : y;
11 }
12
13 struct seg {
14     seg *ls, *rs;
15     int sum, mx, mxl, mxr;
16
17     void* operator new(size_t) {
18         static seg* c;
19         c = new seg[1];
20         c -> ls = c -> rs = NULL;
21         c -> mxl = c -> mxr = c -> mx = c -> sum = 0;
22         return c;
23     }
24
25     inline void change_point(int x) { //change the value of a single point
26         if (x > 0) {
27             sum = mx = mxl = mxr = x;
28         } else {
29             sum = x;
30             mx = mxl = mxr = 0;
31         }
32     }
33
34     inline void update() {
35         if (ls == NULL || rs == NULL) return;
36         sum = ls -> sum + rs -> sum;
37         mx = max(max(ls -> mx, rs -> mx), ls -> mxr + rs -> mxl);
38         mxl = max(ls -> mxl, ls -> sum + rs -> mxl);
39         mxr = max(rs -> mxr, rs -> sum + ls -> mxr);
40     }
41
42     #define mid (l + r >> 1)
43     void build(int l, int r) {
44         if (l == r) {
45             change_point(a[l]);
46             return;
47         }
48         ls = new()seg, ls -> build(l, mid);
49         rs = new()seg, rs -> build(mid + 1, r);
50         update();
51     }
52
53     void modify(int l, int r, int pos, int x) {
54         if (pos < l || r < pos) return;
55         if (l == r) {
56             change_point(x);
57             return;
58         }
59         if (pos <= mid) ls -> modify(l, mid, pos, x);
60         if (mid < pos) rs -> modify(mid + 1 , r, pos, x);
61         update();
62     }
63
64     seg* query(int l, int r, int L, int R) {
65         seg* ret = new()seg;
66         if (l == L && R == r) {
67             *ret = *this;
68             return ret;
69         }
70         if (R <= mid) return ls -> query(l, mid, L, R);
71         if (L > mid) return rs -> query(mid + 1, r, L, R);
72
73         ret -> ls = ls -> query(l, mid, L, mid);
74         ret -> rs = rs -> query(mid + 1, r, mid + 1, R);
75         ret -> update();
76         delete ret -> ls;
77         delete ret -> rs;
78         return ret;
79     }
80     #undef mid
81 } *segment, *ans;
82
83 int main() {
84     int op, x, y;
85     scanf("%d%d", &n, &m);
86     for (int i = 1; i <= n; ++i)
87         scanf("%d", a + i);
88     segment = new()seg;
89     segment -> build(1, n);
90     for (int i = 1; i <= m; ++i) {
91         scanf("%d%d%d", &op, &x, &y);
92         if (op == 0) {
93             segment -> modify(1, n, x, y);
94         } else {
95             ans = segment -> query(1, n, x, y);
96             printf("%d\n", ans -> mx);
97             delete ans;
98         }
99     }
100     return 0;
101 }
View Code

CST2018 3-2 Not Found (20%)

CST2018 3-3 Hacker (20%)

$18^5$其实并不大，直接预处理hash一下就好了。

  1 #include <cstdio>
2 #include <cstring>
3 #include "crc.h"
4
5 using namespace std;
6 const char charset[] = "0123456789tsinghua";
7 const char setlen = 18;
8 const int P2 = 38734667;
9 const char LEN = 20;
10 int hashTable[P2], flag[P2];
11
12 char code[LEN];
13 char pwd[LEN];
14
15 int n;
16 char salt[LEN];
17 int saltlen;
18
19 int test_cnt;
20
21 inline int encode_char(char ch) {
22     switch(ch) {
23         case '0' : return 1;
24         case '1' : return 2;
25         case '2' : return 3;
26         case '3' : return 4;
27         case '4' : return 5;
28         case '5' : return 6;
29         case '6' : return 7;
30         case '7' : return 8;
31         case '8' : return 9;
32         case '9' : return 10;
33         case 't' : return 11;
34         case 's' : return 12;
35         case 'i' : return 13;
36         case 'n' : return 14;
37         case 'g' : return 15;
38         case 'h' : return 16;
39         case 'u' : return 17;
40         case 'a' : return 18;
41     }
42 }
43
44 inline char decode_char(int x) {
45     switch(x) {
46         case 1 : return '0';
47         case 2 : return '1';
48         case 3 : return '2';
49         case 4 : return '3';
50         case 5 : return '4';
51         case 6 : return '5';
52         case 7 : return '6';
53         case 8 : return '7';
54         case 9 : return '8';
55         case 10 : return '9';
56         case 11 : return 't';
57         case 12 : return 's';
58         case 13 : return 'i';
59         case 14 : return 'n';
60         case 15 : return 'g';
61         case 16 : return 'h';
62         case 17 : return 'u';
63         case 18 : return 'a';
64     }
65 }
66
67 inline int encode(char* str) {
68     int len = strlen(str);
69     int encodeNumber = 0;
70     for (int i = 0; i < len; ++i)
71         encodeNumber = 19 * encodeNumber + encode_char(str[i]);
72     return encodeNumber;
73 }
74
75 inline void swap(char &x, char &y) {
76     char t;
77     t = x;
78     x = y;
79     y = t;
80 }
81
82 inline void decode(char* str, int x) {
83     int t = 0;
84     while (x) {
85         str[t] = decode_char(x % 19);
86         x = x / 19;
87         t += 1;
88     }
89     for (int i = 0; i * 2 < t; ++i) {
90         swap(str[i], str[t - i - 1]);
91     }
92     str[t] = 0;
93 }
94
95 int _union(char *str, unsigned char *input) {
96     int i = 0;
97     for (; str[i]; ++i) input[i] = str[i];
98     for (int j = 0; salt[j]; ++j) input[i++] = salt[j];
99     input[i] = 0;
100     return i;
101 }
102
103 inline bool check_eq(int x, int y) {
104     char str[10];
105     decode(str, x);
106     unsigned char input[20];
107     int i = _union(str, input);
108     int CRC32Value1 = crc32(input, i);
109     if (CRC32Value1 == y) return 1;
110     return 0;
111 }
112
113 void insert_hash(int x, int y) {
114     int hash = ((x % P2) + P2) % P2;
115     while (hashTable[hash] != -1) {
116         if (check_eq(hashTable[hash], x)) {
117             flag[hash] = 1;
118             return;
119         }
120         hash += 1;
121     }
122     hashTable[hash] = y;
123 }
124
125 void update_pwd(char x) {
126     for (int i = 0; i <= 5; ++i)
127         pwd[i] = pwd[i + 1];
128     pwd[6] = x;
129     pwd[7] = 0;
130 }
131
132 void get_hash(int x) {
133     int hash = ((x % P2) + P2) % P2;
134     while (hashTable[hash] != -1) {
135         if (check_eq(hashTable[hash], x)) {
136             if (flag[hash] == 1) {
137                 puts("duplicate");
138                 return;
139             }
140             char ans[10];
141             decode(ans, hashTable[hash]);
142             printf("%s\n", ans);
143             update_pwd(ans[0]);
144             return;
145         }
146         hash += 1;
147     }
148     puts("No");
149 }
150
151 void make_hash(char* str) {
152     unsigned char input[20];
153     int i = _union(str, input);
154     int CRC32Value = crc32(input, i); //calculate CRC32
155     insert_hash(CRC32Value, encode(str));
156 }
157
158 void dfs(int len) {
159     for (int i = 0; i < setlen; ++i) {
160         code[len] = charset[i];
161         code[len + 1] = 0;
162         make_hash(code);
163         if (len < 4) dfs(len + 1);
164     }
165 }
166
167 void find_hash() {
168     int CRC32Value;
169     scanf("%d", &CRC32Value);
170     get_hash(CRC32Value);
171 }
172
173 int main() {
174     int len;
175     int oper;
176     scanf("%d\n", &n);
177     scanf("%s\n", salt);
178     saltlen = strlen(salt);
179     for (int i = 0; i < P2; ++i)
180         hashTable[i] = -1, flag[i] = 0;
181
182     dfs(0);
183     while (n--) {
184         scanf("%d\n", &oper);
185         if (oper == 0) {
186             find_hash();
187         }
188         if (oper == 1) {
189             make_hash(pwd);
190         }
191     }
192     return 0;
193 }
View Code

CST2018 3-4 kth (20%)

  1 #include "kth.h"
2 #include <cstdio>
3
4 using namespace std;
5 const int N = 5e5 + 5;
6 const int K = 26e5 + 5;
7
8 int X[N], Y[N], Z[N];
9
10 template<class T> inline void swap(T &x, T &y) {
11     register T tmp;
12     tmp = x, x = y, y = tmp;
13 }
14
15 struct heap {
16     heap *ls, *rs;
17     int _X, _Y, _Z;
18     int dep;
19
20     void *operator new(size_t, int __X, int __Y, int __Z) {
21         static heap mempool[K], *c = mempool;
22         c -> ls = c -> rs = NULL;
23         c -> dep = 1;
24         c -> _X = __X, c -> _Y = __Y, c -> _Z = __Z;
25         return c++;
26     }
27
28     friend inline bool compare_greater(heap *x, heap *y) {
29         return compare(X[y -> _X], Y[y -> _Y], Z[y -> _Z], X[x -> _X], Y[x -> _Y], Z[x -> _Z]);
30     }
31
32     #define Dep(p) (p ? p -> dep : 0)
33     friend heap* merge(heap *x, heap *y) {
34         if (!x) return y;
35         if (!y) return x;
36         if (compare_greater(x, y)) swap(x, y);
37         x -> rs = merge(x -> rs, y);
38         if (Dep(x -> rs) > Dep(x -> ls)) swap(x -> ls, x -> rs);
39         x -> dep = Dep(x -> rs) + 1;
40         return x;
41     }
42     #undef Dep
43
44     inline heap* pop() {
45         return merge(ls, rs);
46     }
47 } *root;
48
49
50 inline bool check_less(int flag, int x, int y) {
51     if (flag == 1) return compare(x, 1, 1, y, 1, 1);
52     if (flag == 2) return compare(1, x, 1, 1, y, 1);
53     if (flag == 3) return compare(1, 1, x, 1, 1, y);
54 }
55
56 inline void swap(int *a, int x, int y) {
57     int t;
58     t = a[x];
59     a[x] = a[y];
60     a[y] = t;
61 }
62
63 void sort(int l, int r, int flag, int *A) {
64     if (l >= r) return;
65     swap(A[(l + r >> 1)], A[r]);
66     int x = A[r], i = l - 1;
67     for (int j = l; j <= r; ++j) {
68         if (check_less(flag, A[j], x)) {
69             i++;
70             swap(A, i, j);
71         }
72     }
73     i += 1;
74     A[r] = A[i];
75     A[i] = x;
76     sort(l, i - 1, flag, A);
77     sort(i + 1, r, flag, A);
78 }
79
80 void init(int n) {
81     for (int i = 1; i <= n; ++i)
82         X[i] = Y[i] = Z[i] = i;
83     sort(1, n, 1, X);
84     sort(1, n, 2, Y);
85     sort(1, n, 3, Z);
86 }
87
88 inline void insert(int _X, int _Y, int _Z) {
89     root = merge(root, new(_X, _Y, _Z)heap);
90 }
91
92 void get_kth(int n, int k, int *x, int *y, int *z) {
93     init(n); //sort for x, y and z
94     root = new(1, 1, 1)heap;
95     int _X, _Y, _Z;
96     while (--k) {
97         _X = root -> _X, _Y = root -> _Y, _Z = root -> _Z;
98         if (_Z != n) insert(_X, _Y, _Z + 1);
99         if (_Z == 1) {
100             if (_Y == 1 && _X != n) insert(_X + 1, _Y, _Z);
101             if (_Y != n) insert(_X, _Y + 1, _Z);
102         }
103         root = root -> pop();
104     }
105     *x = X[root -> _X], *y = Y[root -> _Y], *z = Z[root -> _Z];
106 }
View Code

CST2018 3-5 Prefix (20%)

 1 #include <cstdio>
2 #include <cstring>
3
4 using namespace std;
5 typedef long long ll;
6 const int N = 2e7 + 5;
7
8 int f[N];
9 int cnt[N];
10 char str[N];
11 int len;
12
13 void KMP(int len) {
14     int i = 0, j = -1;
15     f[0] = -1;
16     while (i < len) {
17         if (j == -1 || str[i] == str[j]) {
18             i += 1;
19             j += 1;
20             f[i] = j;
21         }
22         else j = f[j];
23     }
24     f[0] = 0;
25 }
26
27 int main() {
28     gets(str);
29     len = strlen(str);
30     KMP(len);
31     ll ans = 0;
32     memset(cnt, 0, sizeof(cnt));
33     for (int i = 1; i <= len; ++i) {
34         cnt[i] = cnt[f[i]];
35         cnt[i]++;
36         ans += cnt[i];
37     }
38     printf("%lld\n", ans);
39     return 0;
40 }
View Code

CST2018 3-6 Match (20%)

Treap的应用：

  1 #include <cstdio>
2
3 using namespace std;
4 const int N = 4e5 + 5;
5 const int LEN = 10e5 + 5;
6 const int P1 = 951413;
7 const int P2 = 1e9 + 7;
8
9 int n, m;
10
11 template<class T> inline void swap(T &x, T &y) {
12     register T tmp;
13     tmp = x, x = y, y = tmp;
14 }
15
16
17 namespace treap {
18     struct node;
19     node *root, *null;
20     int base[LEN];
21
22     inline int cal_hash(int hash1, int sz1, int ch, int hash2, int sz2) {
23         int ret = (hash2 + 1ll * ch * base[sz2] % P2) % P2;
24         ret = (ret + 1ll * hash1 * base[sz2 + 1] % P2) % P2;
25         return ret;
26     }
27
28     struct node {
29         node *ls, *rs;
30         int sz, rev, hashl, hashr;
31         int ch;
32
33         #define Len (1 << 16)
34         inline void* operator new(size_t, int _v = 0) {
35             static node *mempool, *c;
36             if (mempool == c)
37                 mempool = (c = new node[Len]) + Len;
38             c -> ls = c -> rs = null;
39             c -> sz = 1;
40             c -> rev = 0;
41             c -> hashl = c -> hashr = c -> ch = _v;
42             return c++;
43         }
44         #undef Len
45
46         inline void reverse() {
47             rev ^= 1;
48             swap(ls, rs);
49             swap(hashl, hashr);
50         }
51
52         inline node* push() {
53             if (rev) {
54                 ls -> reverse(), rs -> reverse();
55                 rev = 0;
56             }
57             return this;
58         }
59
60         inline node* update() {
61             sz = ls -> sz + rs -> sz + 1;
62             ls -> push(), rs -> push();
63             hashl = cal_hash(ls -> hashl, ls -> sz, ch, rs -> hashl, rs -> sz);
64             hashr = cal_hash(rs -> hashr, rs -> sz, ch, ls -> hashr, ls -> sz);
65             return this;
66         }
67     };
68
69     inline void init() {
70         null = new()node;
71         null -> ls = null -> rs = null;
72         null -> sz = null -> hashl = null -> hashr = 0;
73
74         base[0] = 1;
75         for (int i = 1; i < LEN; ++i)
76             base[i] = 1ll * base[i - 1] * P1 % P2;
77     }
78
79     inline unsigned int Rand() {
80         static unsigned int res = 2333;
81         return res += res << 2 | 1;
82     }
83     inline int random(int x, int y) {
84         return Rand() % (x + y) < x;
85     }
86
87     void build(node *&p, int l, int r, int *a) {
88         if (l > r) {
89             p = null;
90             return;
91         }
92         p = new(a[l + r >> 1])node;
93         if (l == r) {
94             p -> update();
95             return;
96         }
97         build(p -> ls, l, (l + r >> 1) - 1, a);
98         build(p -> rs, (l + r >> 1) + 1, r, a);
99         p -> update();
100     }
101
102     void merge(node *&p, node *x, node *y) {
103         if (x == null || y == null)
104             p = x == null ? y -> push() : x -> push();
105         else if (random(x -> sz, y -> sz)) {
106             p = x -> push();
107             merge(p -> rs, x -> rs, y);
108         } else {
109             p = y -> push();
110             merge(p -> ls, x, y -> ls);
111         }
112         p -> update();
113     }
114
115     void split(node *p, node *&x, node *&y, int k) {
116         if (!k) {
117             x = null, y = p -> push();
118             return;
119         }
120         if (k == p -> sz) {
121             x = p -> push(), y = null;
122             return;
123         }
124         if (p -> ls -> sz >= k) {
125             y = p -> push();
126             split(p -> ls, x, y -> ls, k);
127             y -> update();
128         } else {
129             x = p -> push();
130             split(p -> rs, x -> rs, y, k - p -> ls -> sz - 1);
131             x -> update();
132         }
133     }
134 }
135 using namespace treap;
136
137 int a[N];
138
139 int main() {
140     char ch;
141     int op;
142     int pos, tmp;
143     int pos1, pos2, len;
144     node *x, *y, *z;
145     int hash1, hash2, ans = 0;
146     scanf("%d %d\n", &n, &m);
147     for (int i = 1; i <= n; ++i) {
148         ch = getchar();
149         while (!('a' <= ch && ch <= 'z')) ch = getchar();
150         a[i] = ch - 'a' + 1;
151     }
152
153     init();
154     build(root, 1, n, a);
155     while (m--) {
156         scanf("%d", &op);
157         if (op == 1) {
158             scanf("%d", &pos);
159             ch = getchar();
160             while (!('a' <= ch && ch <= 'z')) ch = getchar();
161             tmp = ch - 'a' + 1;
162             split(root, x, y, pos);
163             z = new(tmp)node;
164             merge(root, x, z); merge(root, root, y);
165             //root = x + y, new_root = x + z + y
166         }
167         if (op == 2) {
168             scanf("%d", &pos);
169             split(root, x, y, pos - 1); split(y, y, z, 1);
170             merge(root, x, z);
171             //root = x + y + z, new_root = x + z
172         }
173         if (op == 3) {
174             scanf("%d %d", &pos1, &pos2);
175             split(root, x, y, pos1 - 1), split(y, y, z, pos2 - pos1 + 1);
176             y -> reverse();
177             merge(root, x, y -> push()), merge(root, root, z);
178             //root = x + y + z, y -> rev
179         }
180         if (op == 4) {
181             scanf("%d %d %d", &pos1, &pos2, &len);
182             split(root, x, y, pos1 - 1), split(y, y, z, len);
183             hash1 = y -> hashl;
184             merge(root, x, y), merge(root, root, z);
185
186             split(root, x, y, pos2 - 1), split(y, y, z, len);
187             hash2 = y -> hashl;
188             merge(root, x, y), merge(root, root, z);
189             ans += (hash1 == hash2);
190         }
191     }
192     printf("%d\n", ans);
193     return 0;
194 }
View Code

CST2018 3-7 History (15%)

CST2018 3-8 Shortest (15%)

posted on 2018-12-24 01:15  Xs酱~  阅读(...)  评论(...编辑  收藏