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 }
CST2018 3-2 Not Found (20%)
内存有点小,在考虑按层建立trie树?
不太会。
CST2018 3-3 Hacker (20%)
$18^5$其实并不大,直接预处理hash一下就好了。
冲突的话直接记录输出duplicate。
比较简单。
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 }
CST2018 3-4 kth (20%)
可以先通过3n次比较进行排序。
一个数组的话直接二分就好了。
要是两个数组可以丢堆里面。
三个不会【摊手
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 }
CST2018 3-5 Prefix (20%)
一道简单的KMP,就是考虑每个节点为结尾多出来多少重复的。
比较简单。
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 }
CST2018 3-6 Match (20%)
Treap的应用:
插入:基本操作。
删除:基本操作。
翻转:基本操作。
比较大小:用hash比较。
所以要记录两个值:以某个节点为根的顺序的hash和逆序的hash。
写起来比较麻烦。
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 }
CST2018 3-7 History (15%)
强制在线。
简单hash。
CST2018 3-8 Shortest (15%)
堆优化Dijkstra。
其实我觉得spfa加SLF还是能过。。。
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen