1. 程式人生 > >[CCPC2017]湘潭邀請賽

[CCPC2017]湘潭邀請賽

構造 數列 每一個 names 一行 int emp 前綴 pop

題目鏈接:http://202.197.224.59/OnlineJudge2/index.php/Problem/index/p/14/

D.模擬,按照原圖每一個字符變成一個a*b的矩陣構造新矩陣。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 111;
 5 int n, m, a, b;
 6 char G[maxn][maxn];
 7 char GG[maxn][maxn];
 8 
 9 
10 int main() {
11     // freopen("in", "r", stdin);
12 while(~scanf("%d%d%d%d",&n,&m,&a,&b)) { 13 memset(GG, 0, sizeof(GG)); 14 for(int i = 1; i <= n; i++) scanf("%s", G[i]+1); 15 for(int i = 1; i <= n; i++) { 16 for(int j = 1; j <= m; j++) { 17 for(int ii = 1; ii <= a; ii++) {
18 for(int jj = 1; jj <= b; jj++) { 19 GG[(i-1)*a+ii][(j-1)*b+jj] = G[i][j]; 20 } 21 } 22 } 23 } 24 for(int i = 1; i <= n*a; i++) printf("%s\n", GG[i]+1); 25 } 26 }

E.由於選取的區間點l,r都是不重復的,那麽可以將整個問題描述為前綴和取2*m個點,每個點都不重復。

對整個數列排序,從兩頭取就行了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 const int maxn = 100100;
 6 LL a[maxn], s[maxn];
 7 int n, m, c;
 8 
 9 int main() {
10     // freopen("in", "r", stdin);
11     while(~scanf("%d%d%d",&n,&m,&c)) {
12         memset(s, 0, sizeof(s));
13         for(int i = 1; i <= n; i++) {
14             scanf("%I64d", &a[i]);
15             s[i] = s[i-1] + a[i];
16         }
17         sort(s, s+n+1);
18         LL ret = 0;
19         LL tmp = 0;
20         int lo = 0, hi = n;
21         for(int i = 1; i <= m; i++) {
22             tmp += abs(s[hi]-s[lo]) - c;
23             hi--; lo++;
24             ret = max(ret, tmp);
25         }
26         printf("%I64d\n", ret);
27     }
28     return 0;
29 }

H.先用djikstra求出這棵樹上的樹直徑,兩個端點的再向其余邊,最大的值加入到mst的權值中就行了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 typedef pair<LL, LL> pii;
 6 typedef struct Edge { LL v, w, next; }Edge;
 7 const LL maxn = 100100;
 8 LL n, hcnt;
 9 LL head[maxn];
10 Edge edge[maxn<<1];
11 LL d[2][maxn];
12 
13 void adde(LL u, LL v, LL w) {
14     edge[hcnt].v = v, edge[hcnt].w = w;
15     edge[hcnt].next = head[u]; head[u] = hcnt++;
16 }
17 
18 LL dij(LL id, LL u) {
19     memset(d[id], -1, sizeof(d[id]));
20     priority_queue<pii> pq;
21     pq.push(pii(0, u)); d[id][u] = 0;
22     while(!pq.empty()) {
23         pii tmp = pq.top(); pq.pop();
24         LL pw = tmp.first;
25         u = tmp.second;
26         for(LL i = head[u]; ~i; i=edge[i].next) {
27             LL v = edge[i].v, w = edge[i].w;
28             if(d[id][u] < pw) continue;
29             if(d[id][v] == -1 || d[id][v] > d[id][u] + w) {
30                 d[id][v] = d[id][u] + w;
31                 pq.push(pii(d[id][v], v));
32             }
33         }
34     }
35     LL w = 0;
36     for(LL i = 1; i <= n; i++) {
37         if(w < d[id][i]) {
38             w = d[id][i]; u = i;
39         }
40     }
41     return u;
42 }
43 
44 
45 int main() {
46     // freopen("in", "r", stdin);
47     LL u, v, w;
48     while(~scanf("%I64d", &n)) {
49         hcnt = 0;
50         memset(head, -1, sizeof(head));
51         for(LL i = 0; i < n - 1; i++) {
52             scanf("%I64d%I64d%I64d",&u,&v,&w);
53             adde(u, v, w); adde(v, u, w);
54         }
55         LL lo = dij(0, 1);
56         LL hi = dij(1, lo);
57         dij(0, hi);
58         LL ret = d[0][lo];
59         for(LL i = 1; i <= n; i++) {
60             if(i == lo || i == hi) continue;
61             ret += max(d[0][i], d[1][i]);
62         }
63         printf("%I64d\n", ret);
64     }
65 }

I.簡單推下會發現整個式子表示的是一個數列上選取兩個點,求兩個點的最小間隔。最小間隔是gcd(n,m),那麽選中間的位置就會使式子最小。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 const int maxn = 111;
 6 LL n, m;
 7 LL gcd(LL x, LL y) {
 8     return y == 0 ? x : gcd(y, x % y);
 9 }
10 
11 int main() {
12     // freopen("in", "r", stdin);
13     while(cin >> n >> m) {
14         LL a = gcd(n, m);
15         LL b = 2 * n * m;
16         LL g = gcd(a, b);
17         a /= g, b /= g;
18         cout << a << "/" << b << endl;
19     }
20 }

A.相當於求伴隨矩陣的第一列,用高斯消元求出矩陣的逆,輸出第一行。

板子掛了啊。

[CCPC2017]湘潭邀請賽