A.
Ilya and Diplomas

思路:水题了, 随随便便枚举一下,分情况讨论一下就OK了。

code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#define inf 1000000
#define clr(x, y) memset(x, y, sizeof x) using namespace std; int rmina,rmaxa;
int rminb,rmaxb;
int rminc,rmaxc;
int n; int main()
{
scanf("%d", &n);
scanf("%d%d%d%d%d%d", &rmina, &rmaxa, &rminb, &rmaxb, &rminc, &rmaxc);
int d = n - rminb - rminc;
if (d > rmaxa)
{
d = n - rmaxa - rminc;
if (d > rmaxb)
{
d = n - rmaxa - rmaxb;
printf("%d %d %d\n", rmaxa, rmaxb, d);
}
else printf("%d %d %d\n", rmaxa, d, rminc);
}
else printf("%d %d %d\n", d, rminb, rminc); return 0;
}

B.
Pasha and Tea

题意:一共同拥有w升水,有n个男生和n个女生。每一个人都有一个有容量限制a[i]的杯子。每一个男生分到的水容量相等。每一个女生分到的水容量相等。且每一个男生分到的水是女生的二倍。问全部人能分到水的容量的最大值是多少。

思路:设x为在总终状态下每一个女生分到的水的量。a代表女生的最小容量,b代表男生的最小容量。则有x = min(a,b/2,w/3*n)。则 ans = x * 3* n

code :

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define clr(x, y) memset(x, y, sizeof x)
#define inf 1000000000
using namespace std; const int maxn = 300005; int a[maxn];
int n, w; int main()
{
scanf("%d%d", &n, &w);
for (int i = 0; i < 2*n; i++) scanf("%d", &a[i]);
sort(a, a + 2*n);
double x0 = (double)w / (3*n);
double x1 = (double)a[0];
double x2 = (double)a[n] / 2; x0 = min(x0, x1);
x0 = min(x0, x2); x0 = x0 * 3 * n; printf("%f\n", x0); return 0;
}

C.
Arthur and Table

题意:给一个有n个腿的桌子,每一个腿有其长度li,同一时候移除某个腿须要消费di的能量,当长度为最大值的腿的个数大于桌腿的总数的时候,桌子处于平稳状态,输入给出n,li,di问将桌子变成平稳状态所须要的耗费的能量的最小值。

思路:第一眼看上去肯定是要去枚举最大长度的桌腿了,可是怎么样高速的计算确定桌腿后达到平稳状态所须要花费的能量呢? 这个能量包含两部分,一部分是将长度大于当前正在枚举的桌腿的桌腿所有删掉所须要的能量,一部分是删掉使被枚举的长度的桌腿个数大于一半所要消耗的能量。 一開始我把所有的注意力所有都放在了单个的桌腿上,然后在计算复杂度的时候怎么算都感觉会超时。 后来才注意到题目的key ------- di 的大小仅仅有200, 能够依照di对桌脚进行分类, 然后从小到大来枚举di,问题就迎刃而解了~~

code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define clr(x, y) memset(x, y, sizeof x)
#define inf 1000000000
using namespace std; const int maxn = 100005; int n;
int L[maxn];
int D[maxn]; int sum[maxn];
int cnt[maxn];
int cnt_d[maxn]; struct pp
{
int li, di; pp(int a = 0, int b = 0) : li(a), di(b) {} } P[maxn]; bool cmp(pp A, pp B)
{
return A.li > B.li;
} int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &L[i]);
for (int i = 0; i < n; i++) scanf("%d", &D[i]);
for (int i = 0; i < n; i++) P[i] = pp(L[i],D[i]); clr(sum, 0); clr(cnt, 0); clr(cnt_d, 0); for (int i = 0; i < n; i++)
{
sum[L[i]] += D[i];
cnt[L[i]] ++;
cnt_d[D[i]] ++;
} sort(P, P + n, cmp); int coa, ss, cnta, ans; coa = 0;
cnta = 0;
ans = inf; for (int i = 0; i < n; i++)
{
ss = coa;
int v = P[i].li;
int j;
for (j = i; j < n; j++)
{
if (P[j].li != v) break;
cnt_d[P[j].di]--;
}
i = j-1; int nn = n - cnta;
int cha;
if (cnt[v] == 1) cha = nn - 1;
else cha = nn - (cnt[v] - 1) * 2 - 1;
for (int i = 1; i <= 200; i++)
{
if (cha > cnt_d[i])
{
ss += cnt_d[i] * i;
cha -= cnt_d[i];
}
else
{
if (cha >= 0) ss += i * cha;
break;
}
}
ans = min(ans, ss);
cnta += cnt[v];
coa += sum[v];
} printf("%d\n", ans); return 0;
}

题意:给出一个无向图(图可能不联通)。问最少增加多少条边能够使图具有一个奇环,并计算有多少种加边的方法。

思路: 题目事实上不是非常难。可是自己做的时候也是磨了好久才把题目给磨出来, 做法是这种:首先有一个大家都懂的事实:要构成奇环增加边的个数不会超过3条。然后再分情况讨论增加0,1,2,3条边的情况。

首先对图进行黑白染色,在染色的同一时候统计每一个联通块中黑色节点的个数。 还有白色节点的个数。然后讨论

Case 0: 假设存在一个联通块黑白染色不成功。则肯定存在一个奇环,此时所须要增加的边数就为0,其方案数固定为1。(假设有一条边的两端颜色是一样的则染色不成功)

Case 1: 对于一个联通块。假设用一条边将两个黑色点或者白色点连起来,就能形成一个奇环。所以就能够通过一開始所统计的每一个联通块中黑白节点的个数高速的计算出来。

Case 2: 假设每一个联通块都是1个顶点或者两个顶点,则用2条边就能形成环,这样的就统计一下一个点的连通块和两个点的连通块各有多少个再用组合数学搞一搞即可了。

Case 3:   所有是独立点的情况, 从中任意取三个点就能够了~~~

ps: 黑白染色事实上直接跑一遍dfs(or bfs) 即可了。 我太年轻的先跑了一个生成树,然后则染色,事实上没有必要~。

code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define clr(x, y) memset(x, y, sizeof x)
#define inf 1000000000
using namespace std; const int maxn = 200005; vector<int> G[maxn]; struct edge
{
int st,ed;
bool flag;
} E[maxn]; int n, m;
int par[maxn];
int col[maxn];
int white[maxn];
int black[maxn];
int ta; void init(int n_)
{
for(int i = 0; i <= n_; i++) par[i] = i;
} int Find(int x)
{
if (x == par[x]) return x;
return par[x] = Find(par[x]);
}
void unit(int x, int y)
{
x = Find(x);
y = Find(y);
if (x == y) return ;
par[y] = x;
}
bool same(int x, int y)
{
return Find(x) == Find(y);
} void dfs(int u, int &wh, int &bl)
{
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i];
if (col[v] != -1) continue;
col[v] = col[u]^1;
col[v] == 0? wh++ : bl++;
dfs(v, wh, bl);
}
} int main()
{
scanf("%d%d", &n, &m);
int st, ed;
for (int i = 0; i < m; i++)
{
scanf("%d%d", &E[i].st, &E[i].ed);
E[i].flag = false;
}
init(n);
for (int i = 0; i < m; i++)
{
if (!same(E[i].st, E[i].ed))
{
unit(E[i].st, E[i].ed);
G[E[i].st].push_back(E[i].ed);
G[E[i].ed].push_back(E[i].st);
E[i].flag = true;
}
}
clr(col, -1); clr(white, 0); clr(black, 0); ta = 0;
for (int i = 1; i <= n; i++)
{
if (col[i] == -1)
{
int wh = 1;
int bl = 0;
col[i] = 0;
dfs(i, wh, bl);
white[ta] = wh;
black[ta++] = bl;
}
}
for (int i = 0; i < m; i++)
{
if (E[i].flag == true) continue;
if (col[E[i].st] == col[E[i].ed])
{
printf("0 1\n");
return 0;
}
}
long long w = 0;
for (int i = 0; i < ta; i++)
{
if (white[i] > 1) w += (long long)white[i]*(white[i]-1)/2;
if (black[i] > 1) w += (long long)black[i]*(black[i]-1)/2;
}
if (w > 0)
{
printf("1 %lld\n", w);
return 0;
}
int cnt = 0;
int tmp = n;
for (int i = 0; i < ta; i++)
{
if (white[i]+black[i] > 1) cnt++;
}
for (int i = 0; i < ta; i++)
{
if (white[i]+black[i] > 1)
{
cnt--;
tmp -= 2;
w += tmp;
w += 2*cnt;
}
else
{
tmp --;
w += cnt;
}
}
if (w > 0)
{
printf("2 %lld\n", w);
return 0;
}
w += (long long)n*(n-1)*(n-2)/6;
printf("3 %lld\n", w);
return 0; }

E. Ann and Half-Palindrome

题意: 首先题目定义了一个半回文串:一个串是半回文串,当且仅当。这个中间轴左边的奇数位置上的字符与其对称位置上的字符同样,题目给出一个串s,和整数k让你求出s的全部半回文子串中字典序第k大的串。s的长度是5000。

思路:这道题目做起来也可谓是波折满满啊, 一開始听刘神说是暴力,就自己敲了一个最最暴力的做法,尼玛啊O(n^3)的方法你怕不怕。然后一算肯定超时啊,就在想怎么来优化,感觉枚举子串的地方没有什么可优化的了。 就在想判回文的地方有没有什么能够更快的方法,没想出来(还是太弱了),然后刘神告诉我说用区间dp的思想随便预处理一下即可了,顿时恍然大悟,立即又去改了一发,发现超内存 ->___->,然后刘神有告诉我说用动态字典树啊。然后我就去改了字典树。发现T了~~~~, 一看刘神的姿势才发现字典树的插入是O(n)的。可是他没插入一个就相当于插入了全部的以插入串开头的前缀子串,所以在枚举子串的时候仅仅有枚举头即可了~~~。又改了一发最后才过...

当中字典树的每一个节点都多维护一个域用来存,其子树中有多少个半回文串,之后找第K大的串就用类似平衡树上dfs查找某个节点的思想不断的查找左右子树即可了。当中另一些小的细节须要注意~~~

code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define clr(x, y) memset(x, y, sizeof x)
#define inf 1000000000
using namespace std; string s;
int k;
vector<string> vv; int dp[5005][5005]; int dfs(int i, int j)
{
if (i == j) return dp[i][j] = 1;
if (j < i) return dp[i][j] = 1; if (dp[i][j] != -1) return dp[i][j];
if (dfs(i+2,j-2) && s[i] == s[j]) return dp[i][j] = 1;
return dp[i][j] = 0;
} class Trie
{
public:
int flag;
int num;
Trie* next[2];
Trie()
{
flag=0;
num=0;
next[0] = next[1] = 0;
}
} * root; int dfs(Trie * p)
{
if (!p) return 0;
p->num += p->flag;
p->num += dfs(p->next[0]);
p->num += dfs(p->next[1]);
return p->num;
}
string solve(Trie * p, int k)
{
Trie * lson = p->next[0], *rson = p->next[1];;
int lnum, rnum;
if (lson == 0) lnum = 0;
else lnum = lson->num;
if (rson == 0) rnum = 0;
else rnum = rson->num; if (p->flag >= k) return "";
else if (lnum + p->flag >= k) return "a" + solve(lson,k-p->flag);
else return "b" + solve(rson, k - lnum - p->flag);
} void Trie_insert(int st, int ed)
{
Trie* p= root;
for(int i = st; i < ed; i++)
{
int index;
if (s[i] == 'a') index = 0;
else index = 1; if(!p->next[index]){
p->next[index]=new Trie;
}
p=p->next[index];
if (dfs(st,i)) p->flag++;
}
} int main()
{
cin>>s>>k;
int len = s.length();
clr(dp, -1);
root = new Trie();
for (int i = 0; i < len; i++)
{
Trie_insert(i, len);
}
dfs(root);
cout<< solve(root,k) <<endl; return 0;
}

补完了一场题目。给自己加个油~~

Codeforces Round #311 (Div. 2) A,B,C,D,E的更多相关文章

  1. Codeforces Round #311 (Div. 2) E. Ann and Half-Palindrome 字典树/半回文串

    E. Ann and Half-Palindrome Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contes ...

  2. Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 图论

    D. Vitaly and Cycle Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/p ...

  3. Codeforces Round #311 (Div. 2) C. Arthur and Table Multiset

    C. Arthur and Table Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/p ...

  4. Codeforces Round #311 (Div. 2)B. Pasha and Tea 水题

    B. Pasha and Tea Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/prob ...

  5. Codeforces Round #311 (Div. 2) A. Ilya and Diplomas 水题

    A. Ilya and Diplomas Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/ ...

  6. Codeforces Round #311 (Div. 2) E - Ann and Half-Palindrome(字典树+dp)

    E. Ann and Half-Palindrome time limit per test 1.5 seconds memory limit per test 512 megabytes input ...

  7. Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 奇环

    题目链接: 点这里 题目 D. Vitaly and Cycle time limit per test1 second memory limit per test256 megabytes inpu ...

  8. Codeforces Round #311 (Div. 2) D - Vitaly and Cycle(二分图染色应用)

    http://www.cnblogs.com/wenruo/p/4959509.html 给一个图(不一定是连通图,无重边和自环),求练成一个长度为奇数的环最小需要加几条边,和加最少边的方案数. 很容 ...

  9. Codeforces Round #311 (Div. 2)

    我仅仅想说还好我没有放弃,还好我坚持下来了. 最终变成蓝名了,或许这对非常多人来说并不算什么.可是对于一个打了这么多场才好不easy加分的人来说,我真的有点激动. 心脏的难受或许有点是由于晚上做题时太 ...

随机推荐

  1. 微信小程序之底部弹框预约插件

    代码地址如下:http://www.demodashi.com/demo/13982.html 一.前期准备工作: 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.c ...

  2. 使用samba实现linux与windows文件共享

                       1,安装samba                              sudo apt-get install samba                 ...

  3. proc文件系统分析

    来源: ChinaUnix博客 日期: 2008.01.03 11:46 (共有条评论) 我要评论   二 proc文件系统分析  根据前面的分析,我们可以基本确定对proc文件系统的分析步骤.我将按 ...

  4. 【LeetCode】69. Sqrt(x) (2 solutions)

    Sqrt(x) Implement int sqrt(int x). Compute and return the square root of x. 解法一:牛顿迭代法 求n的平方根,即求f(x)= ...

  5. 【LeetCode】106. Construct Binary Tree from Inorder and Postorder Traversal

    Construct Binary Tree from Inorder and Postorder Traversal Given inorder and postorder traversal of ...

  6. 构造函数、析构函数、赋值与初始化、explicit关键字

    一.构造函数.默认构造函数 (1).构造函数 构造函数是特殊的成员函数 创建类类型的新对象,系统自动会调用构造函数 构造函数是为了保证对象的每个数据成员都被正确初始化 函数名和类名完全相同 不能定义构 ...

  7. atitit.故障排除------有时会错误com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: soc

    atitit.故障排除------有时会错误com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: soc ...

  8. 32位嵌入式微处理器(processor)一览

    32位嵌入式微处理器(processor)一览 由于嵌入式系统的专用型与定制性,与全球PC市场不同,没有一种微处理器或者微处理器公司可以主导嵌入式系统.本文分析了当前市场上主流的一些32位嵌入式微处理 ...

  9. C++ virtual继承

    C++ virtual继承的还有一种名称是菱形继承.主要目的是用于解决从不同类继承来的同名数据成员在内存中有不同的拷贝.造成数据不统一的问题,以致于在进行类释放时造成内存泄漏. 将共同的基类作为虚基类 ...

  10. linux下编译 静态库、动态库,动态库依赖静态库

    xx.o : xx.h xx.cpp -lstdc++ -o xx.o -c xx.cpp -I ./ libxx.a : xx.o ar -crv libxx.a xx.o libTest.so : ...