随笔 - 374  文章 - 2  评论 - 101  0

反正没时间写,先把简要题解(嘴巴A题)都给他写了记录一下。

upd:任务倒是完成了,我也自闭了。

 

CST2018 2-1 Meteorites:

  乘法版的石子合并,堆 + 高精度。

  写起来有点烦貌似。

upd:由于内存问题我高精度是动态开点,同时用的是可并堆(比较简单)。

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 
  5 using namespace std;
  6 typedef double lf;
  7 typedef long long ll;
  8 const lf pi = acos(-1.0);
  9 const int N = 200005;
 10 const int MaxLen = 2000005;
 11 const int MOD = 10000;
 12 
 13 struct BigNumber;
 14 inline int getint();
 15 inline void getInt(BigNumber &res); // get Big number
 16 inline void print(ll *num, int Len);
 17 
 18 template<class T> inline void swap(T &x, T &y) {
 19     register T tmp;
 20     tmp = x, x = y, y = tmp;
 21 }
 22 
 23 int n;
 24 
 25 struct Complex {
 26     lf x, y;
 27     
 28     Complex(lf _x = 0, lf _y = 0) : x(_x), y(_y) {
 29     }
 30     ~Complex() {
 31     }
 32     
 33     Complex operator +(const Complex &_c) {
 34         return Complex(x + _c.x, y + _c.y);
 35     }
 36     Complex operator -(const Complex &_c) {
 37         return Complex(x - _c.x, y - _c.y);
 38     }
 39     Complex operator *(const Complex &_c) {
 40         return Complex(x * _c.x - y * _c.y, x * _c.y + y * _c.x);
 41     }
 42     Complex operator *(const lf &_x) {
 43         return Complex(_x * x, _x * y);
 44     }
 45     Complex operator !() {
 46         return Complex(x, -y);
 47     }
 48 } w[MaxLen], A[MaxLen], B[MaxLen], C[MaxLen];
 49 
 50 struct BigNumber {
 51     ll *x;
 52     int len;
 53     
 54     BigNumber() {
 55         x = new ll[1];
 56         x[0] = 0;
 57         len = 0;
 58     }
 59     
 60     void destroy() {
 61         if (x) delete[] x;
 62     }
 63     
 64     ~BigNumber() {
 65         destroy();
 66     }
 67     
 68     void ChangeSize(int length) {
 69         if (x) delete[] x;
 70         x = new ll[length + 1];
 71         memset(x, 0, (length + 1) * sizeof(x));
 72         len = 0;
 73     }
 74     
 75     void zero() {
 76         ChangeSize(0);
 77         x[0] = 0;
 78         len = 0;
 79     }
 80     void one() {
 81         ChangeSize(0);
 82         x[0] = 1;
 83         len = 0;
 84     }
 85     
 86     void copy(const BigNumber &_num) {
 87         ChangeSize(_num.len);
 88         len = _num.len;
 89         for (int i = len; i >= 0; --i)
 90             x[i] = _num.x[i];
 91     }
 92     
 93     inline bool operator > (const BigNumber &_num) const {
 94         if (len > _num.len) return 1;
 95         if (len < _num.len) return 0;
 96         for (int i = len; i >= 0; --i) {
 97             if (x[i] > _num.x[i]) return 1;
 98             if (x[i] < _num.x[i]) return 0;
 99         }
100         return 1;
101     }
102     
103     void print() {
104         for (int i = len; i >= 0; --i) 
105             printf(i == len ? "%lld" : "%04lld", x[i]);
106         puts("");
107     }
108 };
109 
110 struct heap {
111     heap *ls, *rs;
112     BigNumber num;
113     int dep;
114     
115     void *operator new(size_t) {
116         static heap mempool[N << 2], *c = mempool;
117         c -> ls = c -> rs = NULL;
118         c -> dep = 1;
119         c -> num.zero();
120         return c++;
121     }
122     
123     inline void get_value(const BigNumber &_num) {
124         num.copy(_num);
125     }
126     
127     #define Dep(p) (p ? p -> dep : 0)
128     inline void update() {
129         dep = Dep(rs) + 1;
130     }
131     
132     friend heap* merge(heap *x, heap *y) {
133         if (!x) return y;
134         if (!y) return x;
135         if (x -> num > y -> num) swap(x, y);
136         x -> rs = merge(x -> rs, y);
137         if (Dep(x -> rs) > Dep(x -> ls))
138             swap(x -> ls, x -> rs);
139         x -> update();
140         return x;
141     }
142     #undef Dep
143     
144     inline heap* pop() {
145         this -> num.ChangeSize(0);
146         return merge(ls, rs);
147     }
148 } *Root;
149 
150 
151 void work(const BigNumber &a, const BigNumber &b, BigNumber &c) {
152     int n = a.len, m = b.len, l = a.len + b.len + 4;
153     c.ChangeSize(l);
154     
155     for (int k = 0; k <= l; ++k) c.x[k] = 0;
156     
157     for (int i = 0; i <= n; ++i)
158         for (int j = 0; j <= m; ++j)
159             c.x[i + j] += a.x[i] * b.x[j];            
160     for (int k = 0; k < l; ++k) {
161         c.x[k + 1] += c.x[k] / MOD;
162         c.x[k] %= MOD;
163     }
164     
165     while (c.x[l] == 0) --l;
166     c.len = l;
167 }
168 
169 int main() {
170     BigNumber ans, tmp, a, b, c;
171     heap *tmp_node;
172     
173     n = getint();
174     tmp.one();
175         
176     Root = new()heap;
177     Root -> get_value(tmp);    
178     
179     for (int i = 1; i <= n; ++i) {
180         getInt(tmp);
181         tmp_node = new()heap;
182         tmp_node -> get_value(tmp);
183         
184         Root = merge(Root, tmp_node);
185     }
186     
187     
188     ans.one();
189     for (int i = 1; i <= n; ++i) {
190         a.copy(Root -> num);
191         Root = Root -> pop();
192         b.copy(Root -> num);
193         Root = Root -> pop();
194         /*
195         puts("a and b:");
196         a.print();
197         b.print();
198         puts("---------");
199         */
200         work(a, b, c);
201         /*
202         puts("c:");
203         c.print();
204         */
205         tmp.copy(ans);
206         if (i != 1) {
207             /*
208             puts("----");
209             tmp.print();
210             c.print();
211             */
212             work(tmp, c, ans);
213         }
214         /*
215         puts("ans:");
216         ans.print();
217         */
218         tmp_node = new()heap;
219         tmp_node -> get_value(c);
220         
221         Root = merge(Root, tmp_node);
222     }
223     ans.print();
224     
225     return 0;
226 }
227 
228 const int BUF_SIZE = 30;
229 char buf[BUF_SIZE], *buf_s = buf, *buf_t = buf + 1;
230 #define isdigit(x) ('0' <= x && x <= '9')
231 #define PTR_NEXT() { \
232     if (++buf_s == buf_t) \
233         buf_s = buf, buf_t = buf + fread(buf, 1, BUF_SIZE, stdin); \
234 }
235 
236 int getint() {
237     register int x = 0;
238     while (!isdigit(*buf_s)) PTR_NEXT();
239     while (isdigit(*buf_s)) {
240         x = x * 10 + *buf_s - '0';
241         PTR_NEXT();
242     }
243     return x;
244 }
245 
246 void getInt(BigNumber &res) {
247     static ll num[50];
248     static int len, Len, cnt, base;
249     memset(num, 0, sizeof(num)), len = 0;
250     for (int i = 0; i < 50; ++i) num[i] = 0;
251 
252     while (!isdigit(*buf_s)) PTR_NEXT();
253     while (isdigit(*buf_s) && buf_s != buf_t) {
254         num[len++] = *buf_s - '0';
255         PTR_NEXT();
256     }
257     len -= 1;
258     
259     res.ChangeSize((len + 4) / 4 - 1);
260     Len = -1, cnt = 0;
261     for (int i = len; i >= 0; --i) {
262         cnt++;
263         if (cnt % 4 == 1) Len += 1, base = 1;
264         res.x[Len] += base * num[i];
265         base *= 10;
266     }
267     res.len = Len;
268     
269     /*
270     for (int i = 0; i <= len; ++i)
271         printf("%lld ", num[i]);
272     puts("");    
273     
274     res.print();
275     */
276 }
View Code

 

CST2018 2-2 Circuit

  首先是一个二进制trie + 贪心,但是由于有间隔限制,所以这个trie要支持插入和删除标记操作。

  写起来并不麻烦。

upd:哪个xx卡内存。。。要把指针改成数组下标,同时把叶子和非叶子分开。

  1 #include <cstdio>
  2 #include <cstring>
  3     
  4 using namespace std;
  5 typedef unsigned long long ull;
  6 const int N = 5e5 + 5;
  7 const int SIZE = 18e6 + 5;
  8 int n, k;
  9 int a[100];
 10 ull f[N];
 11 
 12 struct trie_node {
 13     int son[2];
 14     int cnt;
 15 } trie[SIZE];
 16 int Root;
 17 int cnt = 0;
 18 
 19 struct leaf_node {
 20     int cnt;
 21     int next;
 22 } leaf[N];
 23 int cnt_leaf = 0;
 24 
 25 
 26 int get_new() {
 27     ++cnt;
 28     trie[cnt].son[0] = trie[cnt].son[1] = -1;
 29     trie[cnt].cnt = 0;
 30     return cnt;
 31 }
 32 
 33 int get_new_leaf() {
 34     ++cnt_leaf;
 35     leaf[cnt_leaf].cnt = 0;
 36     leaf[cnt_leaf].next = -1;
 37     return cnt_leaf;
 38 }
 39 
 40 struct Queue {
 41     int next, value;
 42 } q[N];
 43 int size;
 44 
 45 void init() {
 46     Root = get_new();
 47 }
 48 
 49 void trie_add(int *a, int id) {
 50     int tmp = Root;
 51     for (int i = 1; i <= 64; ++i) {
 52         trie[tmp].cnt += 1;
 53         if (trie[tmp].son[a[i]] == -1) {
 54             if (i != 64) trie[tmp].son[a[i]] = get_new();
 55             else trie[tmp].son[a[i]] = get_new_leaf();
 56         }
 57         tmp = trie[tmp].son[a[i]];
 58     }
 59     
 60     //leaf
 61     leaf[tmp].cnt += 1;
 62     int t = leaf[tmp].next;
 63     if (t == -1) {
 64         size += 1;
 65         leaf[tmp].next = size;
 66         q[size].next = -1;
 67         q[size].value = id;
 68     } else {
 69         while (q[t].next != -1) t = q[t].next;
 70         size += 1;
 71         q[t].next = size;
 72         q[size].next = -1;
 73         q[size].value = id;
 74     }    
 75 }
 76 
 77 void trie_delete(int *a) {
 78     int tmp = Root;
 79     for (int i = 1; i <= 64; ++i) {
 80         trie[tmp].cnt -= 1;
 81         tmp = trie[tmp].son[a[i]];
 82     }
 83     
 84     //leaf
 85     leaf[tmp].cnt -= 1;
 86     leaf[tmp].next = q[leaf[tmp].next].next;
 87 }
 88 
 89 int trie_find(int *a, int id) {
 90     int tmp = Root;
 91     int t;
 92     for (int i = 1; i <= 64; ++i) {
 93         if (i != 64) {
 94             t = trie[tmp].son[!a[i]];
 95             if (t != -1 && trie[t].cnt != 0)
 96                 tmp = trie[tmp].son[!a[i]];
 97             else
 98                 tmp = trie[tmp].son[a[i]];
 99         } else {
100             t = trie[tmp].son[!a[i]];
101             if (t != -1 && leaf[t].cnt != 0)
102                 tmp = trie[tmp].son[!a[i]];
103             else
104                 tmp = trie[tmp].son[a[i]];
105         }
106     }
107     int x = leaf[tmp].next;
108     while (q[x].value == id) {
109         x = q[x].next;
110     }
111     return q[x].value;
112 }
113 
114 //--------------------------------------------------------------------
115 //--------------------------------------------------------------------
116 
117 void split(ull x) {
118     memset(a, 0, sizeof(a));
119     for (int i = 64; x; x >>= 1, --i) {
120         a[i] = x % 2;
121     }
122     /*
123     for (int i = 1; i <= 64; ++i)
124         printf("%d", a[i]);
125     puts("");
126     */
127 }
128 
129 void add_in_trie(int i) {
130     if (i < 0 || i > n) return;
131     //printf("Add    : %d %llu\n", i, f[i]);
132     split(f[i]);
133     trie_add(a, i);
134 }
135 
136 void delete_in_trie(int i) {
137     if (i < 0 || i > n) return;
138     //printf("Delete : %d %llu\n", i, f[i]);
139     split(f[i]);
140     trie_delete(a);
141 }
142 
143 int get_ans(int i) {
144     //printf("Find   : %d %llu\n", i, f[i]);
145     split(f[i]);
146     return trie_find(a, i);
147 }
148 
149 
150 int main() {
151     ull x;
152     scanf("%d%d", &n, &k);
153     /*
154     for (int i = 1; i <= n; ++i) {
155         scanf("%llu", &x);
156         printf("%llu\n", x);
157         f[i] = x;
158         split(x);        
159     }
160     */
161     
162     int L, R, nowL, nowR;
163     nowL = 1, nowR = 0;
164     L = 1 - k - 1;
165     R = 1 + k + 1;
166     init();
167     for (int i = 1; i <= n; ++i) {
168         //add in trie
169         while (nowR < R) {
170             nowR += 1;
171             scanf("%llu", &f[nowR]);
172             split(f[nowR]);
173             add_in_trie(nowR);
174         }
175         //delete in trie
176         while (nowL < L) {
177             delete_in_trie(nowL);
178             nowL += 1;
179         }
180         
181         //printf("%d %d %d\n", i, nowL, nowR);
182         printf("%d\n", get_ans(i) - 1);
183         
184         //change the segment
185         L += 1;
186         R += 1;
187         if (L > n) L = n;
188         if (R > n) R = n;
189     }
190     
191     return 0;
192 }
View Code

 

 CST2018 2-3-1 Mooney(basic)

  求一个有向图的强连通分量个数,直接tarjan就好了。

  写起来 = 抄板子。

upd:没写。

 

CST2018 2-3-2 Mooney

  两个小问题:

    第一个就是求最短路,Dijkstra。

    第二个先按照前一道题tarjan求强连通分量,然后对DAG树形DP。

  写起来有点麻烦。

upd:第一问我写了SLF优化的spfa,应该不卡,第二问要注意有的连通分量走不到T要删掉。

  1 #include <cstdio>
  2 
  3 using namespace std;
  4 const int N = 5e5 + 5;
  5 const int M = 12e5 + 5;
  6 const int inf = 1e9;
  7 
  8 
  9 int n, m;
 10 int f[N];
 11 int tot, first[N];
 12 int TOT, FIRST[N];
 13 
 14 struct edge {
 15     int next, to;
 16     edge() {}
 17     edge(int _n, int _t) : next(_n), to(_t) {}
 18 } e[M], E[M];
 19 
 20 inline void add_edge(int x, int y) {
 21     e[++tot] = edge(first[x], y), first[x] = tot;
 22 }
 23 
 24 int q[N], v[N], dis[N];
 25 void spfa(int S) {
 26     int p, x, y, l, r;
 27     
 28     for (x = 1; x <= n; ++x)
 29         dis[x] = inf;
 30     
 31     q[0] = S, dis[S] = (f[S] == 0), v[S] = 1;
 32     for (l = r = 0; l != (r + 1) % N; ) {
 33         p = q[l], ++l %= N;
 34         for (x = first[p]; x; x = e[x].next) {
 35             y = e[x].to;
 36             if (dis[p] + (f[y] == 0) < dis[y]) {
 37                 dis[y] = dis[p] + (f[y] == 0);
 38                 if (!v[y]) {
 39                     v[y] = 1;
 40                     if (dis[y] < dis[q[l]]) q[(l += N - 1) %= N] = y;
 41                     else q[++r %= N] = y;
 42                 }
 43             }
 44         }
 45         v[p] = 0;
 46     }
 47 }
 48 
 49 int __main1__() {
 50     spfa(1);
 51     printf("%d\n", dis[n]);
 52 }
 53 
 54 
 55 int low[N], dfn[N], vis[N], inq[N], s[N], w[N];
 56 int Cnt[N], num;
 57 int VIS[N], ans[N];
 58 int cnt, top;
 59 int S, T;
 60 
 61 inline int min(int x, int y) {
 62     return x < y ? x : y;
 63 }
 64 
 65 inline int max(int x, int y) {
 66     return x > y ? x : y;
 67 }
 68 
 69 
 70 void dfs(int p){
 71     low[p] = dfn[p] = ++cnt;
 72     vis[p] = inq[p] = 1;
 73     s[++top] = p;
 74     int x, y;
 75     for (x = first[p]; x; x = e[x].next)
 76         if (!vis[(y = e[x].to)]){
 77             dfs(y);
 78             low[p] = min(low[p], low[y]);
 79         }else
 80         if (inq[y]) low[p] = min(low[p], dfn[y]);
 81     if (low[p] == dfn[p]){
 82         ++num, y = 0;
 83         while (y != p){
 84             inq[(y = s[top--])] = 0;
 85             w[y] = num;
 86             if (f[y] == 1) 
 87                 ++Cnt[num];
 88         }
 89     }
 90 }
 91 
 92 inline void ADD_EDGE(int x, int y) {
 93     E[++TOT] = edge(FIRST[x], y), FIRST[x] = TOT;
 94 }
 95 
 96 void rebuild_graph() {
 97     int x, y;
 98     for (int i = 1; i <= n; ++i)
 99         for (x = first[i]; x; x = e[x].next)
100             if (w[i] != w[(y = e[x].to)])
101                 ADD_EDGE(w[i], w[y]);
102 }
103 
104 int tag[N];
105 
106 void work(int p) {
107     int x, y;
108     ans[p] = 0;
109     if (p == T) {
110         tag[p] = 1;
111         ans[p] = Cnt[T];
112         return;
113     }
114     for (x = FIRST[p]; x; x = E[x].next) {
115         if (!VIS[y = E[x].to]) {
116             VIS[y] = 1;
117             work(y);
118         }
119         if (tag[y]) tag[p] = 1;
120         ans[p] = max(ans[p], ans[y]);
121     }
122     if (tag[p] == 1)
123         ans[p] += Cnt[p];
124 }
125 
126 int __main2__() {
127     for (int i = 1; i <= n; ++i)
128         if (!vis[i])
129             dfs(i);
130     rebuild_graph();
131     
132     S = w[1];
133     T = w[n];
134     work(S);
135     
136     printf("%d\n", ans[S]);
137 }
138 
139 int main() {
140     int x, y;
141     char ch;
142     
143     scanf("%d%d\n", &n, &m);
144     for (int i = 1; i <= n; ++i) {
145         ch = getchar();
146         while (ch != 'm' && ch != 'M')
147             ch = getchar();
148         if (ch == 'M') f[i] = 0;
149         if (ch == 'm') f[i] = 1;
150     }
151     
152     for (int i = 1; i <= m; ++i) {
153         scanf("%d %d", &x, &y);
154         add_edge(x + 1, y + 1);
155     }
156     
157     __main1__();
158     __main2__();    
159         
160     return 0;
161 }
View Code

 

CST2018 2-4 Sort

  我记得好像是原题,忘了咋做了。

  大概想法是归并排序的时候分析归并子序列1的前两个数和子序列2的前一个数的大小,不能证明其上界。。。

  写起来不麻烦。。就是不知道对不对。

upd:自闭了,四路归并写不来。

 

CST2018 2-5 ChromPoly

  也没有什么想法,直接dfs好像就可以了。

  问题是怎么判断两张图是同构的,这样子可以大幅度剪枝,甚至在小情况的时候进行打表预处理。

  然后这是个NP问题,我xxxx。

  我还是决定用hash来做。。但是还是没想好怎么hash

  写起来不麻烦,如果hash搞定了的话。

upd:并不是hash,有别人的代码,戳这里。写到一半自闭了,不想写了。

 

CST2018 2-6 Temperature

  二维数组,单点修改,矩阵求和,在线算法。

  好像可以写二维的树状数组,子矩阵可以通过左上角二维前缀和解决。

  写起来比较简单。

upd:好像没什么好讲的,要是每道题都这么简单就好了。

 1 #include <cstdlib>
 2 #include "temperature.h"
 3 
 4 using namespace std;
 5 const int N = 1205;
 6 const int M = 1205;
 7 
 8 int sum[N][M];
 9 int _t[N][M];
10 
11 void change(int, int, int);
12 
13 void init(int n, int m, int **temp) {
14     for (int i = 1; i <= n; ++i)
15         for (int j = 1; j <= m; ++j) {
16             change(i, j, temp[i][j]);
17             _t[i][j] = temp[i][j];
18         }
19 }
20 
21 inline int Q(int x, int y) {
22     int res = 0;
23     for (int i = x; i; i -= i&(-i))
24         for (int j = y; j; j -= j&(-j))
25             res += sum[i][j];
26     return res;
27 }
28 
29 int query(int x1, int y1, int x2, int y2) {
30     return (Q(x2, y2) - Q(x2, y1 - 1) - Q(x1 - 1, y2) + Q(x1 - 1, y1 - 1)) / ((x2 - x1 + 1) * (y2 - y1 + 1));
31 }
32 
33 void change(int x, int y, int temp) {
34     int del = temp - _t[x][y];
35     _t[x][y] = temp;
36     for (int i = x; i < N; i += i&(-i))
37         for (int j = y; j < M; j += j&(-j))
38             sum[i][j] += del;
39 }
View Code

 

CST2018 2-7 Virus

  就是求所有离0最远的1,直接bfs就好了。

  写起来非常简单。

upd: 好像也没什么好讲的,但是少了5分。。。有毒。

 1 #include <cstdio>
 2 
 3 using namespace std;
 4 const int N = 1005;
 5 const int M = 1005;
 6 const int CNT = N * M;
 7 
 8 const int dx[] = {1, -1, 0, 0};
 9 const int dy[] = {0, 0, 1, -1};
10 
11 int ans;
12 int n, m;
13 int w[N][M];
14 int x[CNT], y[CNT];
15 int time[CNT], vis[CNT];
16 int q[CNT], l, r;
17 int cnt, cnt_virus;
18 
19 
20 inline void _max(int &x, int y) {
21     if (x < y) x = y;
22 }
23 
24 inline void push_q(int x, int y, int t) {
25     r++;
26     q[r] = w[x][y];
27     vis[w[x][y]] = 1;
28     time[w[x][y]] = t;
29     ans += t;
30     ++cnt_virus;
31 }
32 
33 inline bool IN(int x, int y) {
34     return 0 < x && x <= n && 0 < y && y <= m;
35 }
36 
37 int main() {
38     char ch;
39     int C;
40     int _x, _y, __x, __y;
41     scanf("%d%d", &n, &m);
42     cnt = 0;
43     l = 1, r = 0;
44     for (int i = 1; i <= n; ++i)
45         for (int j = 1; j <= m; ++j) {
46             w[i][j] = ++cnt;
47             x[cnt] = i, y[cnt] = j;
48             
49             ch = getchar();
50             while (ch != '0' && ch != '1') ch = getchar();
51             if (ch == '0') push_q(i, j, 0);
52         }
53     while (l <= r) {
54         C = q[l];
55         _x = x[C], _y = y[C];
56         for (int i = 0; i < 4; ++i) {
57             __x = _x + dx[i], __y = _y + dy[i];
58             if (IN(__x, __y) && !vis[w[__x][__y]])
59                 push_q(__x, __y, time[w[_x][_y]] + 1);
60         }
61         ++l;
62     }
63     printf("%d\n", ans);
64     return 0;
65 }
View Code

 

 

CST2018 2-8 MST

  求最小生成树。

  ctrl c + ctrl v = AC。

 

20分题:1,2,3-2,4, 5, 6。

15分题:3-1, 7, 8。

吐槽:15分题和20分题真的是一个难度的吗?助教nb。

posted on 2018-11-27 21:56 Xs酱~ 阅读(...) 评论(...) 编辑 收藏