Codeforces Round #311 (Div. 2) 完整题解

来源:互联网 发布:gson解析json数据 编辑:程序博客网 时间:2024/04/27 02:28

A题:贪心就行了,第一个尽量大,第二个尽量大。

#include <iostream>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <algorithm>#include <cstring>#include <climits>#include <cstdlib>#include <cmath>#include <time.h>#define maxn 100005#define maxm 200005#define eps 1e-7#define mod 1000000007#define INF 0x3f3f3f3f#define PI (acos(-1.0))#define lowbit(x) (x&(-x))#define mp make_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R#define pii pair<int, int>#pragma comment(linker, "/STACK:16777216")typedef long long LL;typedef unsigned long long ULL;//typedef int LL; using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}// headvoid work(){int n, t1, t2, t3;int l1, l2, l3, r1, r2, r3;scanf("%d", &n);scanf("%d%d", &l1, &r1);scanf("%d%d", &l2, &r2);scanf("%d%d", &l3, &r3);t1 = min(r1, (n - l2 - l3));n -= t1;t2 = min(r2, (n - l3));n -= t2;t3 = n;printf("%d %d %d\n", t1, t2, t3);}int main(){work();return 0;}

B题:简单题,求出女生的杯子的容量尽量大

#include <iostream>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <algorithm>#include <cstring>#include <climits>#include <cstdlib>#include <cmath>#include <time.h>#define maxn 200005#define maxm 200005#define eps 1e-7#define mod 1000000007#define INF 0x3f3f3f3f#define PI (acos(-1.0))#define lowbit(x) (x&(-x))#define mp make_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R#define pii pair<int, int>#pragma comment(linker, "/STACK:16777216")typedef long long LL;typedef unsigned long long ULL;//typedef int LL; using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}// headint a[maxn];int n, m;void work(){scanf("%d%d", &n, &m);for(int i = 1; i <= 2 * n; i++) scanf("%d", &a[i]);sort(a+1, a+2*n+1);int t1 = a[1], t2 = a[n+1];double ans = min(1.0 * t1, t2 * 1.0 / 2);ans = 3 * ans * n;ans = min(ans, m * 1.0);printf("%.9f\n", ans);}int main(){work();return 0;}

C题:枚举最后剩下的长度,然后和这个长度相同的不用砍,长度大的全砍,小的尽量砍价值低的。d只有200,暴力就行,大的话要用平衡树。代码写的很搓。。。其实枚举1-10^5很好写,后来才想到。

#include <iostream>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <algorithm>#include <cstring>#include <climits>#include <cstdlib>#include <cmath>#include <time.h>#define maxn 200005#define maxm 200005#define eps 1e-7#define mod 1000000007#define INF 0x3f3f3f3f#define PI (acos(-1.0))#define lowbit(x) (x&(-x))#define mp make_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R#define pii pair<int, int>#pragma comment(linker, "/STACK:16777216")typedef long long LL;typedef unsigned long long ULL;//typedef int LL; using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}// headpii p[maxn];int c[300];int n;int solve(int pos, int last){for(int i = pos; i < last; i++) c[p[i].second]--;int tt = last - pos;tt = (tt - 1);int res = 0;for(int i = pos; i < last; i++) res += p[i].second;for(int i = 200; i >= 0; i--) {if(!c[i]) continue;if(tt >= c[i]) tt -= c[i], res += i * c[i];else res += tt * i, tt = 0;if(tt == 0) break;}return res;}void work(){int x, tot = 0;scanf("%d", &n);for(int i = 1; i <= n; i++) {scanf("%d", &x);p[i] = mp(x, 0);}for(int i = 1; i <= n; i++) {scanf("%d", &x);tot += x;p[i].second = x;}sort(p+1, p+n+1);for(int i = 1; i <= n; i++) c[p[i].second]++;p[n+1] = mp(INF, 0);int last = n+1, ans = INF;for(int i = n-1; i >= 1; i--) {if(p[i].first == p[i+1].first) continue;ans = min(ans, tot - solve(i+1, last));last = i+1;}ans = min(ans, tot - solve(1, last));printf("%d\n", ans);}int main(){work();return 0;}
D题:简单图论。答案只可能是0,1,2,3.。。如果原图有一个连通块是二分图那么答案就是0,原图没边答案就是3,原图每个连通块点数不超过2,答案就是2。。剩下的就是原图每一个连通块都是二分图,那么加一条边就行了。。。。方案数每种情况分别统计。

#include <iostream>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <algorithm>#include <cstring>#include <climits>#include <cstdlib>#include <cmath>#include <time.h>#define maxn 200005#define maxm 200005#define eps 1e-7#define mod 1000000007#define INF 0x3f3f3f3f#define PI (acos(-1.0))#define lowbit(x) (x&(-x))#define mp make_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R#define pii pair<int, int>#pragma comment(linker, "/STACK:16777216")typedef long long LL;typedef unsigned long long ULL;//typedef int LL; using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}// headstruct Edge{int v;Edge *next;}*H[maxn], E[maxm], *edges;int vis[maxn];int a[maxn];int b[maxn];int n, m, cnt, T;void addedges(int u, int v){edges->v = v;edges->next = H[u];H[u] = edges++;}void init(){edges = E;memset(H, 0, sizeof H);}bool dfs(int u){cnt++;bool ok = 1;if(vis[u] == 1) a[T]++;else b[T]++;for(Edge *e = H[u]; e; e = e->next) {int v = e->v;if(vis[v]) {if(vis[v] == vis[u]) ok = false;}else vis[v] = 3 - vis[u], ok &= dfs(v);}return ok;}void work(){scanf("%d%d", &n, &m);if(m == 0) {LL ans = (LL)(n-1) * n * (n-2);ans /= 6;printf("3 %I64d\n", ans);return;}int u, v;init();for(int i = 1; i <= m; i++) {scanf("%d%d", &u, &v);addedges(u, v);addedges(v, u);}int mx = 0;T = 0;for(int i = 1; i <= n; i++) if(!vis[i]) {cnt = 0;vis[i] = 1;T++;if(!dfs(i)) {printf("0 1\n");return;}mx = max(mx, cnt);}if(mx == 2) {printf("2 %I64d\n", (LL)(n-2) * m);return;}LL ans = 0;for(int i = 1; i <= T; i++) {if(a[i] + b[i] >= 3) {ans += (LL)a[i] * (a[i]  - 1)/ 2;ans += (LL)b[i] * (b[i] - 1) / 2;}}printf("1 %I64d\n", ans);}int main(){work();return 0;}

E题:先n^2预处理出is[i][j]是不是符合奇回文。然后按字典序对所有子串暴力求第k个奇回文串。实现方法有很多,可以暴力对所有后缀排序,或者后缀数组。。。这里使用后缀自动机。。。统计的时候dfs后缀自动机就行了。。后来发现这题的字符集只有2。。。。所以字典树的空间也是够的。。。用字典树也是可以的。。

#include <iostream>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <algorithm>#include <cstring>#include <climits>#include <cstdlib>#include <cmath>#include <time.h>#define maxn 5005#define maxm 200005#define eps 1e-7#define mod 1000000007#define INF 0x3f3f3f3f#define PI (acos(-1.0))#define lowbit(x) (x&(-x))#define mp make_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R#define pii pair<int, int>#pragma comment(linker, "/STACK:16777216")typedef long long LL;typedef unsigned long long ULL;//typedef int LL; using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}// headconst int alpha = 26;struct node{int cnt, len, pos;node *ch[alpha], *fa;}*tail, *last, pool[maxm], *root;node *tp[maxm];bool is[maxn][maxn];vector<int> ans;char s[maxn];int c[maxn];int ok, n;node* newnode(int len, int pos){tail->pos = pos, tail->cnt = 0;tail->len = len;tail->fa = NULL;memset(tail->ch, 0, sizeof tail->ch);return tail++;}void init(){tail = pool;last = root = newnode(0, 0);}void add(int c, int pos){node *p = last, *np = newnode(p->len + 1, pos);last = np;for(; p && !p->ch[c]; p = p->fa) p->ch[c] = np;if(!p) np->fa = root;else {node *q = p->ch[c];if(q->len == p->len + 1) np->fa = q;else {node *nq = newnode(p->len + 1, pos);*nq = *q;nq->len = p->len + 1;q->fa = np->fa = nq;for(; p && p->ch[c] == q; p = p->fa) p->ch[c] = nq;}}}void dfs(node *p, int &kk, int path){if(is[p->pos - path + 1][p->pos]) kk -= p->cnt;if(kk <= 0) {ok = true;return;}if(ok) return;for(int i = 0; i < alpha; i++) if(p->ch[i]) {ans.push_back(i);dfs(p->ch[i], kk, path + 1);if(ok) return;ans.pop_back();}}void work(){int kk;scanf("%s%d", s+1, &kk);int n = strlen(s+1);for(int i = n; i >= 1; i--)for(int j = i; j <= n; j++) {is[i][j] = s[i] == s[j];if(i + 2 <= j - 2) is[i][j] &= is[i+2][j-2];}for(int i = 1; i <= n; i++) add(s[i] - 'a', i);int t = 1;for(node *p = root; t <= n; t++) {int tt = s[t] - 'a';p = p->ch[tt];p->cnt++;}int tot = tail - root;for(node *p = root; p < tail; p++) c[p->len]++;for(int i = 1; i <= n; i++) c[i] += c[i-1];for(node *p = root; p < tail; p++) tp[--c[p->len]] = p;for(int i = tot-1; i > 0; i--) tp[i]->fa->cnt += tp[i]->cnt;ok = 0;root->cnt = 0;dfs(root, kk, 0);for(int i = 0; i < ans.size(); i++) printf("%c", ans[i] + 'a');printf("\n");}int main(){init();work();return 0;}



字典树:

#include <iostream>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <cstdio>#include <algorithm>#include <cstring>#include <climits>#include <cstdlib>#include <cmath>#include <time.h>#define maxn 5005#define maxm 25000005#define eps 1e-7#define mod 1000000007#define INF 0x3f3f3f3f#define PI (acos(-1.0))#define lowbit(x) (x&(-x))#define mp make_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R#define pii pair<int, int>#pragma comment(linker, "/STACK:16777216")typedef long long LL;typedef unsigned long long ULL;//typedef int LL; using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}// headconst int alpha = 2;struct node{int l, r, cnt;node *ch[alpha];}pool[maxm], *tail, *root;bool is[maxn][maxn];char s[maxn];int ok, n;node* newnode(){tail->l = tail->r = tail->cnt = 0;return tail++;}void init(){tail = pool;root = newnode();}void insert(int l, int r){node *p = root;for(int i = l; i <= r; i++) {int c = s[i] - 'a';if(!p->ch[c]) p->ch[c] = newnode();p = p->ch[c];p->l = l, p->r = i, p->cnt += is[l][i];}}void dfs(node *p, int &kk){if(ok) return;for(int i = 0; i < alpha; i++) if(p->ch[i]) {if(ok) return;if(kk > p->ch[i]->cnt) {kk -= p->ch[i]->cnt;dfs(p->ch[i], kk);}else {for(int j = p->ch[i]->l; j <= p->ch[i]->r; j++) printf("%c", s[j]);printf("\n");ok = 1;return;}}}void work(){int kk;scanf("%s%d", s+1, &kk);int n = strlen(s+1);for(int i = n; i >= 1; i--)for(int j = i; j <= n; j++) {is[i][j] = s[i] == s[j];if(i + 2 <= j - 2) is[i][j] &= is[i+2][j-2];}for(int i = 1; i <= n; i++) insert(i, n);ok = 0;dfs(root, kk);}int main(){init();work();return 0;}


0 0
原创粉丝点击