Topcoder SRM 608 div1 题解

Easy(300pts):

题目大意:有n个盒子,一共有S个苹果,每个盒子有多少个苹果不知道,但是知道每个盒子的苹果下限和上限。现在要至少选择X个苹果,问如果要保证无论如何都能获得至少X个苹果,至少需要选择多少个盒子。数据满足n<=50。

首先第一个方面,如果我们选择的盒子的下限大于等于X,那么显然我们一定可以获得那么多的苹果,

所以我们将盒子的下限排序,然后从大到小累加即可。

另一方面,如果我们没有选择的盒子的上限小于等于S-X,那么显然我们也一定可以获得那么多的苹果,

于是我们再按照上限排序,然后扫一遍累加即可。

时间复杂度O(nlogn),代码如下:

 1 #include <bits/stdc++.h>
 2 #define Maxn 57
 3 using namespace std;
 4 int n;
 5 int l[Maxn],r[Maxn];
 6 class MysticAndCandies
 7 {
 8     public:
 9     int minBoxes(int C, int X, vector <int> low, vector <int> high)
10     {
11         n=low.size();
12         for (int i=1;i<=n;i++) l[i]=low[i-1];
13         for (int i=1;i<=n;i++) r[i]=high[i-1];
14         sort(l+1,l+n+1);
15         sort(r+1,r+n+1);
16         for (int i=1;i<n+1-i;i++) swap(l[i],l[n+1-i]),swap(r[i],r[n+1-i]);
17         int ans,sum1=0,sum2=0;
18         for (int i=1;i<=n;i++) sum2+=r[i];
19         for (ans=1;ans<=n;ans++)
20         {
21             sum1+=l[ans];
22             sum2-=r[ans];
23             if (sum1>=X||C-sum2>=X) break;
24         }
25         return ans;
26     }
27 };

Medium(600pts):

题目大意:给出一个n个点的有向图,假设长度为L的路径一共有S条(路径可以经过重复的点多次,S也可以是无穷大),问当L非常大的时候,S的量级是L的几次方。当然,有可能S不能用L的几次方表示,那么输出-1。数据满足n<=50。

通过题面来看,就感觉这题很厉害。。。

我们先从一个环来考虑,一个环的长度为L的路径显然只有有数条,那么这个时候S就是L的一次方量级。

然后我们来考虑一个强联通分量,如果这个强联通分量不仅仅只是一个环,那么路径条数就是指数级别的了。

回到原题,我们把原图中的强联通分量全部求出来,

至少图变成了一个DAG,然后发现所有的SCC必须是环,

然后差不多dp之类的都可以做了。

由于这道题n<=50,所以根本不需要什么Tarjan,直接floyed就行了。

时间复杂度O(n^3),代码如下:

 1 #include <bits/stdc++.h>
 2 #define Maxn 57
 3 using namespace std;
 4 bool vis[Maxn][Maxn];
 5 int fa[Maxn],sum[Maxn],sumedge[Maxn];
 6 int r[Maxn],f[Maxn];
 7 int n;
 8 class BigO
 9 {
10     public:
11     int minK(vector <string> graph)
12     {
13         n=graph.size();
14         for (int i=0;i<n;i++)
15             for (int j=0;j<n;j++)
16                 if (graph[i][j]==‘Y‘) vis[i][j]=true; else vis[i][j]=false;
17         for (int i=0;i<n;i++)
18             vis[i][i]=true;
19         for (int k=0;k<n;k++)
20             for (int i=0;i<n;i++)
21                 for (int j=0;j<n;j++)
22                     if (vis[i][k]&&vis[k][j]) vis[i][j]=true;
23         memset(sum,0,sizeof(sum));
24         for (int i=0;i<n;i++)
25             for (int j=0;j<n;j++)
26                 if (vis[i][j]&&vis[j][i])
27                 {
28                     fa[i]=j;
29                     ++sum[j];
30                     break;
31                 }
32         memset(sumedge,0,sizeof(sumedge));
33         for (int i=0;i<n;i++)
34             for (int j=0;j<n;j++)
35                 if (graph[i][j]==‘Y‘&&fa[i]==fa[j]&&i!=j)
36                     ++sumedge[fa[i]];
37         memset(r,0,sizeof(r));
38         memset(f,0,sizeof(f));
39         for (int i=0;i<n;i++)
40         {
41 //the SCC is more than a circle
42             if (sumedge[i]>sum[i]) return -1;
43 //the SCC is more than a point
44             if (sumedge[i]!=0) r[i]=1;
45             f[i]=r[i];
46         }
47         for (int T=0;T<n;T++)
48             for (int i=0;i<n;i++)
49                 for (int j=0;j<n;j++)
50                     if (fa[i]!=fa[j]&&graph[i][j]==‘Y‘)
51                         f[fa[j]]=max(f[fa[j]],f[fa[i]]+r[fa[j]]);
52         int res=0;
53         for (int i=0;i<n;i++)
54             res=max(f[i]-1,res);
55         return res;
56     }
57 };

Hard(900pts):

题目大意:有一个机器人在x轴上,初始位置为0,它接受到了一系列指令,每次向左一个单位或者向右一个单位。如果现在在左边界上,那么就不能再往左了,向左的指令会被忽略;如果现在在右边界上,那么就不能再往右了,向右的指令会被忽略。现在对于minA<=A<=maxA,minB<=B<=maxB,求出以A为左边界,B为右边界的最终位置的总和,数据满足所有数<=5000。

这题是个神结论题,不打算多说。。。

我们假设边界都是无穷大的时候,求出出现过的最左侧位置和最右侧位置。

如果A和B分别大于等于两边边界,那么答案就是最终位置。

如果不是的话,有一个结论就是(a,b)等于(a-1,b+1)-1,然后按照差暴力就可以了。

时间复杂度O(nX+X^2),代码如下:

 1 #include <bits/stdc++.h>
 2 #define Maxa 5007
 3 using namespace std;
 4 int ans[Maxa][Maxa];
 5 string s;
 6 long long res=0;
 7 class OneDimensionalRobot
 8 {
 9     public:
10     long long theSum(vector <string> commands1, vector <string> commands2, int minA, int maxA, int minB, int maxB)
11     {
12         s.clear();
13         for (int i=0;i<commands1.size();i++) s+=commands1[i];
14         for (int i=0;i<commands2.size();i++) s+=commands2[i];
15         int left=0,right=0,pos=0;
16         for (int i=0;i<s.length();i++)
17         {
18             if (s[i]==‘R‘) ++pos; else --pos;
19             if (-pos>left) left=-pos;
20             if (pos>right) right=pos;
21         }
22         memset(ans,0,sizeof(ans));
23         for (int i=minA;i<=maxA;i++)
24             for (int j=minB;j<=maxB;j++)
25             {
26                 if (i>=left&&j>=right) ans[i][j]=pos; else
27                 if (i==minA||j==maxB)
28                 {
29                     int now=0;
30                     for (int k=0;k<s.length();k++)
31                     {
32                         if (s[k]==‘R‘) ++now; else --now;
33                         if (-now>i) now=-i;
34                         if (now>j) now=j;
35                     }
36                     ans[i][j]=now;
37                 } else
38                 {
39                     ans[i][j]=ans[i-1][j+1];
40                     if (left>i-1||right>j) --ans[i][j];
41                 }
42             }
43         for (int i=minA;i<=maxA;i++)
44             for (int j=minB;j<=maxB;j++)
45                 res+=ans[i][j];
46         return res;
47     }
48 };
时间: 2024-10-27 05:13:02

Topcoder SRM 608 div1 题解的相关文章

Topcoder SRM 607 div1题解

好久没来写了,继续继续... Easy(250pts): //前方请注意,样例中带有zyz,高能预警... 题目大意:给你一个字符串,中间有一些是未知字符,请你求出这个字符串的回文子串个数的期望值.数据满足字符最多2500个. 我们考虑每一个子串,它对答案的贡献度就是它是回文串的概率,那么我们扫一遍就可以了, 这样做时间复杂度O(n^3),显然过不去. 我们考虑一下对于一个子串,在判断其是回文串的时候,我们一定是从中间往两边扫的,那么其实中间这些子串我们已经统计过答案了, 也就是说,我们通过枚举

Topcoder SRM 603 div1题解

昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点,每个节点都有一个权值,两人A和B分别进行操作,由A先手,每人可以选择一条边,将它删掉得到两个联通块.游戏不断进行下去,最后只剩下一个节点.A希望最后的节点权值尽可能大,B希望尽可能小,求这个最后的值.数据保证n<=50. 这道题真的是博弈好题啊-(感觉放到ACM很合适啊) 我们考虑第一次A会如何选

Topcoder SRM 605 div1 题解

日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的个数)乘积越大,输出这个最大值.数据满足n<=50,type<=100,abs(taste)<=100000. 这题好像是个贪心,才不是呢啊哼- 首先我们发现,如果若干个汉堡包有同一个type值,那么我们可以把这一些汉堡包看成一个新的大汉堡包,它的type就是原来的type,它的taste就

Topcoder SRM 604 div1题解

CTSC考完跑了过来日常TC--- Easy(250pts): 题目大意:有个机器人,一开始的位置在(0,0),第k个回合可以向四个方向移动3^k的距离(不能不动),问是否可以到达(x,y),数据满足|x|,|y|<=10^9. 这题还是很简单的嘛,口亨--- 首先我们只考虑一个方向,于是发现,每一次可以移动3^k的距离或者不动,于是我们发现这样的序列是有且仅有一个的, 于是我们分开考虑x和y,把两个序列全部预处理出来, 然后直接扫一遍就做完了, 时间复杂度O(log|x|)左右吧,代码如下:

Topcoder SRM 643 Div1 250&lt;peter_pan&gt;

Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*......*pn,我们假设p0,p1,...,pn是单调不降的,那么v里存储的是下标为偶数 的N的质因数p0,p2,p4,...,p(2k).现在要求写一个程序,返回一个vector<long long>ans; ans里存储的是p0,p1,p2,...,pn. Limits Time Limit(m

Topcoder SRM 648 Div1 250

Problem 给一个长度为N的"AB"字符串S,S只含有两种字符'A' 或 'B',设pair(i,j)(0=<i<j<N)表示一对 i,j 使得S[i]='A',S[j]='B'.现给定一个K,求字符串S,使得pair(i,j)的个数恰好为K.若不存在,则返回空串. Limits Time Limit(ms): 2000 Memory Limit(MB): 256 N: [2, 50] K: [0 , N*(N-1)/2 ] Solution 若K>(N/2

Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

Problem Statement      The Happy Letter game is played as follows: At the beginning, several players enter the field. Each player has a lowercase English letter on their back. The game is played in turns. In each turn, you select two players with dif

Topcoder SRM 662 DIV1

FoxesOfTheRoundTable 题意: 给你一个序列,让你生成一个排列,并且这个排列是循环的.使得任意两个相邻数的差的最大值尽量小. 题解: 先排个序,然后从小到大逐个插入.这时容易发现,若要得到最优的策略,只能将现在的这个数插在当前排列中最大的那个数的旁边,这是因为,要插入的这个数是大于当前排列中的任何一个数,故而插入只会产生一个更大的差距,为了使这个差距尽量小,就不得不在最大的数旁边插入. 假如现在的序列就是0 1 2 3 4 5 首先前三个数是没有影响的:0 1 2 插入3:0

topcoder srm 738 div1 FindThePerfectTriangle(枚举)

Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle with the following properties: The coordinates of each vertex are integers between 0 and 3000, inclusive. The perimeter of the triangle must be exactly