码迷,mamicode.com
首页 > 其他好文 > 详细

2015多校被碾压记

时间:2015-07-23 21:24:27      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:

我他妈就是一傻逼。

        ——题记

 

第一场多校:出题数0

 

第一题:

    比赛时候的思路挺接近的了。逐个元素考虑,找到能延伸的最大区间,便可以统计该元素对答案的贡献。

    所谓能延伸的最大区间就是指这个区间没有所考虑元素的约数。

    因为数字的范围很小,所以可以用一个数组来记录每个数字出现的最右的下标。枚举约数,找到所有约数中最右的下标。

    

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 
 6 using namespace std;
 7 
 8 const int maxn = 100000 + 100;
 9 const int MOD = 1000000000 + 7;
10 
11 int n;
12 int a[maxn], l[maxn], r[maxn];
13 int L[maxn], R[maxn];
14 
15 int main()
16 {
17     while(scanf("%d", &n) == 1 && n)
18     {
19         for(int i = 1; i <= n; i++) scanf("%d", a + i);
20         memset(l, 0, sizeof(l));
21         memset(r, 0, sizeof(r));
22 
23         for(int i = 1; i <= n; i++)
24         {
25             L[i] = 0;
26             for(int j = 1; j <= (int)sqrt(a[i] + 0.5); j++) if(a[i] % j == 0)
27             {
28                 L[i] = max(L[i], l[j]);
29                 L[i] = max(L[i], l[a[i] / j]);
30             }
31             l[a[i]] = i;
32         }
33 
34         for(int i = 1; i <= 10000; i++) r[i] = n + 1;
35 
36         for(int i = n; i >= 1; i--)
37         {
38             R[i] = n + 1;
39             for(int j = 1; j <= (int)sqrt(a[i] + 0.5); j++) if(a[i] % j == 0)
40             {
41                 R[i] = min(R[i], r[j]);
42                 R[i] = min(R[i], r[a[i] / j]);
43             }
44             r[a[i]] = i;
45         }
46 
47         int ans = 0;
48         for(int i = 1; i <= n; i++) ans = (ans + (R[i] - i) * (i - L[i])) % MOD;
49 
50         printf("%d\n", ans);
51     }
52 
53     return 0;
54 }
代码君

 

第二题:

    可以用RMQ做,枚举区间左端点,二分右端点,找到合法区间的最右边界。判断是否合法就用RMQ查询区间最大最小值减一下。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int maxn = 100000 + 10;
 7 const int logmaxn = 20;
 8 
 9 int n, k;
10 
11 int a[maxn];
12 
13 int _min[maxn][logmaxn], _max[maxn][logmaxn];
14 
15 void RMQ_init()
16 {
17     for(int i = 0; i < n; i++) _min[i][0] = _max[i][0] = a[i];
18     for(int j = 1; (1 << j) <= n; j++)
19         for(int i = 0; i + (1 << j) - 1 < n; i++)
20         {
21             _min[i][j] = min(_min[i][j-1], _min[i+(1<<(j-1))][j-1]);
22             _max[i][j] = max(_max[i][j-1], _max[i+(1<<(j-1))][j-1]);
23         }
24 }
25 
26 void RMQ(int L, int R, int& Min, int& Max)
27 {
28     int k = 0;
29     while((1<<(k+1)) <= R-L+1) k++;
30     Min = min(_min[L][k], _min[R-(1<<k)+1][k]);
31     Max = max(_max[L][k], _max[R-(1<<k)+1][k]);
32 }
33 
34 int main()
35 {
36     int T; scanf("%d", &T);
37     while(T--)
38     {
39         scanf("%d%d", &n, &k);
40         for(int i = 0; i < n; i++) scanf("%d", a + i);
41         RMQ_init();
42 
43         long long ans = 0;
44         for(int L = 0; L < n; L++)
45         {
46             int l = L, r = n - 1;
47             while(l < r)
48             {
49                 int mid = (l + r) / 2 + 1;
50                 int Min, Max;
51                 RMQ(L, mid, Min, Max);
52                 if(Max - Min < k) l = mid;
53                 else r = mid - 1;
54             }
55             ans += r - L + 1;
56         }
57 
58         printf("%I64d\n", ans);
59     }
60 
61     return 0;
62 }
代码君

 

三四题这种DP表示不会。

 

第五题,作为一个曾经玩了三年魔方的我表示真的不知道还有这么个结论。

 

第七题:

    上来就敲的这道题,WA了,以为我想得太简单了就弃疗了。

    其实是一道很裸的模板题,在原图的基础上把所有最短路的边选出来构一个新图。

    最大流求最小割,总边数 - 边最少的最短路,这就是这题的答案。

    

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <queue>
  6 #include <map>
  7 #define MP make_pair
  8 using namespace std;
  9 
 10 typedef pair<int, int> PII;
 11 
 12 const int maxn = 2000 + 100;
 13 const int maxm = 60000 + 100;
 14 const int INF = 0x3f3f3f3f;
 15 int n, m;
 16 
 17 struct Edge
 18 {
 19     int from, to, dist;
 20     Edge(int u, int v, int d):from(u), to(v), dist(d) {}
 21 };
 22 
 23 int d[maxn];
 24 
 25 struct Dijkstra
 26 {
 27     int n, m, s, t;
 28     bool done[maxn];
 29     vector<Edge> edges;
 30     vector<int> G[maxn];
 31 
 32     void init() { edges.clear(); for(int i = 1; i <= n; i++) G[i].clear(); }
 33 
 34     void AddEdge(int u, int v, int d)
 35     {
 36         edges.push_back(Edge(u, v, d));
 37         edges.push_back(Edge(v, u, d));
 38         m = edges.size();
 39         G[u].push_back(m - 2);
 40         G[v].push_back(m - 1);
 41     }
 42 
 43     void dijkstra()
 44     {
 45         memset(d, 0x3f, sizeof(d));
 46         d[s] = 0;
 47         memset(done, false, sizeof(done));
 48         priority_queue<PII, vector<PII>, greater<PII> > Q;
 49         Q.push(MP(0, s));
 50         while(!Q.empty())
 51         {
 52             PII x = Q.top(); Q.pop();
 53             int u = x.second;
 54             if(done[u]) continue;
 55             done[u] = true;
 56             for(int i = 0; i < G[u].size(); i++)
 57             {
 58                 Edge& e = edges[G[u][i]];
 59                 int v = e.to;
 60                 if(d[v] > d[u] + e.dist)
 61                 {
 62                     d[v] = d[u] + e.dist;
 63                     Q.push(MP(d[v], v));
 64                 }
 65             }
 66         }
 67     }
 68 }solver;
 69 
 70 struct Edge2
 71 {
 72     int from, to, cap, flow;
 73     Edge2(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
 74 };
 75 
 76 struct Dinic
 77 {
 78     int n, m, s, t;
 79     vector<Edge2> edges;
 80     vector<int> G[maxn];
 81     bool vis[maxn];
 82     int d[maxn], cur[maxn];
 83 
 84     void init() { for(int i = 1; i <= n; i++) G[i].clear(); edges.clear(); }
 85 
 86     void AddEdge(int u, int v, int c)
 87     {
 88         edges.push_back(Edge2(u, v, c, 0));
 89         edges.push_back(Edge2(v, u, 0, 0));
 90         m = edges.size();
 91         G[u].push_back(m - 2);
 92         G[v].push_back(m - 1);
 93     }
 94 
 95     bool BFS()
 96     {
 97         memset(vis, false, sizeof(vis));
 98         vis[s] = true;
 99         queue<int> Q;
100         Q.push(s);
101         d[s] = 0;
102 
103         while(!Q.empty())
104         {
105             int u = Q.front(); Q.pop();
106             for(int i = 0; i < G[u].size(); i++)
107             {
108                 Edge2& e = edges[G[u][i]];
109                 int v = e.to;
110                 if(!vis[v] && e.cap > e.flow)
111                 {
112                     vis[v] = true;
113                     d[v] = d[u] + 1;
114                     Q.push(v);
115                 }
116             }
117         }
118 
119         return vis[t];
120     }
121 
122     int DFS(int u, int a)
123     {
124         if(u == t || a == 0) return a;
125         int flow = 0, f;
126         for(int& i = cur[u]; i < G[u].size(); i++)
127         {
128             Edge2& e = edges[G[u][i]];
129             int v = e.to;
130             if(d[v] == d[u] + 1 && (f = DFS(v, min(a, e.cap-e.flow))) > 0)
131             {
132                 flow += f;
133                 e.flow += f;
134                 a -= f;
135                 edges[G[u][i]^1].flow -= f;
136                 if(a == 0) break;
137             }
138         }
139         return flow;
140     }
141 
142     int MaxFlow()
143     {
144         int flow = 0;
145         while(BFS())
146         {
147             memset(cur, 0, sizeof(cur));
148             flow += DFS(s, INF);
149         }
150         return flow;
151     }
152 }g;
153 
154 int a[maxm], b[maxm], c[maxm];
155 int u[maxm], v[maxm], w[maxm];
156 
157 int main()
158 {
159     while(scanf("%d%d", &n, &m) == 2 && n)
160     {
161         solver.n = n;
162         solver.init();
163         solver.s = 1, solver.t = n;
164         for(int i = 0; i < m; i++)
165         {
166             int u, v, d; scanf("%d%d%d", a + i, b + i, c + i);
167             solver.AddEdge(a[i], b[i], c[i]);
168         }
169         solver.dijkstra();
170 
171         int cnt = 0;
172         for(int i = 0; i < m; i++)
173         {
174             if(d[a[i]] + c[i] == d[b[i]])
175             {
176                 u[cnt] = a[i];
177                 v[cnt] = b[i];
178                 w[cnt++] = c[i];
179             }
180             else if(d[b[i]] + c[i] == d[a[i]])
181             {
182                 u[cnt] = b[i];
183                 v[cnt] = a[i];
184                 w[cnt++] = c[i];
185             }
186         }
187 
188         //for(int i = 0; i < cnt; i++) printf("%d  %d  %d\n", u[i], v[i], w[i]);
189 
190         int ans1, ans2;
191         g.n = n;
192         g.s = 1, g.t = n;
193         g.init();
194         for(int i = 0; i < cnt; i++) g.AddEdge(u[i], v[i], 1);
195         g.BFS();
196         ans2 = m - g.d[n];
197         ans1 = g.MaxFlow();
198 
199         printf("%d %d\n", ans1, ans2);
200     }
201 
202     return 0;
203 }
代码君

 

第九题:

    看懂题目的做法了,但是不懂为什么。

    白书上讲了求LCA的倍增算法,属于在线算法。

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <set>
  6 using namespace std;
  7 
  8 const int maxn = 100000 + 100;
  9 const int logmaxn = 20;
 10 
 11 int n, Q;
 12 
 13 vector<int> G[maxn], w[maxn];
 14 
 15 set<int> S;
 16 
 17 // LCA
 18 int dfs_clock;
 19 int dfs[maxn];
 20 int id[maxn];
 21 int dep[maxn];
 22 int fa[maxn];
 23 int cost[maxn];
 24 int anc[maxn][logmaxn];
 25 
 26 void DFS(int u, int father, int depth)
 27 {
 28     dfs[u] = ++dfs_clock;
 29     id[dfs_clock] = u;
 30     fa[u] = father;
 31     dep[u] = depth;
 32     for(int i = 0; i < G[u].size(); i++)
 33     {
 34         int v = G[u][i];
 35         if(v == father) continue;
 36         cost[v] = cost[u] + w[u][i];
 37         DFS(v, u, depth + 1);
 38     }
 39 }
 40 
 41 void preprocess()
 42 {
 43     for(int i = 1; i <= n; i++)
 44     {
 45         anc[i][0] = fa[i];
 46         for(int j = 1; (1 << j) < n; j++) anc[i][j] = -1;
 47     }
 48     for(int j = 1; (1 << j) < n; j++)
 49         for(int i = 1; i <= n; i++)
 50             if(anc[i][j-1] != -1)
 51             {
 52                 int a = anc[i][j-1];
 53                 anc[i][j] = anc[a][j-1];
 54             }
 55 }
 56 
 57 int LCA(int p, int q)
 58 {
 59     int log;
 60     if(dep[p] < dep[q]) swap(p, q);    //dep[p] >= dep[q]
 61     for(log = 1; (1 << log) <= dep[p]; log++); log--;
 62 
 63     for(int i = log; i >= 0; i--)
 64         if(dep[p] - (1 << i) >= dep[q]) p = anc[p][i];
 65     if(p == q) return p;
 66 
 67     for(int i = log; i >= 0; i--)
 68     {
 69         if(anc[p][i] != -1 && anc[p][i] != anc[q][i])
 70         {
 71             p = anc[p][i];
 72             q = anc[q][i];
 73         }
 74     }
 75     return fa[p];
 76 }
 77 
 78 int add(int u)
 79 {
 80     if(S.empty()) return 0;
 81     int x, y;
 82     set<int>::iterator itx, ity;
 83     itx = ity = S.lower_bound(dfs[u]);
 84     itx--;
 85     if(ity == S.begin() || ity == S.end())
 86     {
 87         itx = S.begin();
 88         ity = S.end(); ity--;
 89     }
 90     x = (*itx); x = id[x];
 91     y = (*ity); y = id[y];
 92 
 93     return cost[u] - cost[LCA(x, u)] - cost[LCA(y, u)] + cost[LCA(x, y)];
 94 }
 95 
 96 bool inset[maxn];
 97 
 98 int main()
 99 {
100     //freopen("in.txt", "r", stdin);
101 
102     int T; scanf("%d", &T);
103     for(int kase = 1; kase <= T; kase++)
104     {
105         printf("Case #%d:\n", kase);
106 
107         scanf("%d%d", &n, &Q);
108         for(int i = 1; i <= n; i++) { G[i].clear(); w[i].clear(); }
109         for(int i = 0; i < n - 1; i++)
110         {
111             int u, v, d; scanf("%d%d%d", &u, &v, &d);
112             G[u].push_back(v); w[u].push_back(d);
113             G[v].push_back(u); w[v].push_back(d);
114         }
115 
116         dfs_clock = 0;
117         cost[1] = 0;
118         DFS(1, -1, 0);
119         preprocess();
120 
121         int sum = 0;
122         S.clear();
123         memset(inset, false, sizeof(inset));
124         while(Q--)
125         {
126             int op, x; scanf("%d%d", &op, &x);
127             if(op == 1 && !inset[x])
128             {
129                 inset[x] = true;
130                 sum += add(x);
131                 S.insert(dfs[x]);
132             }
133             else if(op ==2 && inset[x])
134             {
135                 inset[x] = false;
136                 S.erase(dfs[x]);
137                 sum -= add(x);
138             }
139             printf("%d\n", sum);
140         }
141     }
142 
143     return 0;
144 }
代码君

 

 

第二场多校:出题数0

今天心情不好,去刷点别的题发泄一下。改日补

2015多校被碾压记

标签:

原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4671455.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!