SCAU2021春季个人排位赛第四场 (部分题解)

预设应该有:
简单题:AD
中等题:BCF
较难题:EG
A:二分
B:状压DP
C:最短路+二分
D:单调栈
E:后缀数组/后缀自动机
F:贪心+堆
G:2-SAT

状压不会,最短路有些许忘记,先写了其中已经改了的题解先。

 

A题

CodeForces - 371C

Polycarpus loves hamburgers very much. He especially adores the hamburgers he makes with his own hands. Polycarpus thinks that there are only three decent ingredients to make hamburgers from: a bread, sausage and cheese. He writes down the recipe of his favorite "Le Hamburger de Polycarpus" as a string of letters 'B' (bread), 'S' (sausage) и 'C' (cheese). The ingredients in the recipe go from bottom to top, for example, recipe "ВSCBS" represents the hamburger where the ingredients go from bottom to top as bread, sausage, cheese, bread and sausage again.

Polycarpus has nb pieces of bread, ns pieces of sausage and nc pieces of cheese in the kitchen. Besides, the shop nearby has all three ingredients, the prices are pb rubles for a piece of bread, ps for a piece of sausage and pc for a piece of cheese.

Polycarpus has r rubles and he is ready to shop on them. What maximum number of hamburgers can he cook? You can assume that Polycarpus cannot break or slice any of the pieces of bread, sausage or cheese. Besides, the shop has an unlimited number of pieces of each ingredient.

Input

The first line of the input contains a non-empty string that describes the recipe of "Le Hamburger de Polycarpus". The length of the string doesn't exceed 100, the string contains only letters 'B' (uppercase English B), 'S' (uppercase English S) and 'C' (uppercase English C).

The second line contains three integers nbnsnc (1 ≤ nb, ns, nc ≤ 100) — the number of the pieces of bread, sausage and cheese on Polycarpus' kitchen. The third line contains three integers pbpspc (1 ≤ pb, ps, pc ≤ 100) — the price of one piece of bread, sausage and cheese in the shop. Finally, the fourth line contains integer r (1 ≤ r ≤ 1012) — the number of rubles Polycarpus has.

Please, do not write the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

Output

Print the maximum number of hamburgers Polycarpus can make. If he can't make any hamburger, print 0.

Examples

Input

BBBSSC
6 4 1
1 2 3
4

Output

2

Input

BBC
1 10 1
1 10 1
21

Output

7

Input

BSC
1 1 1
1 1 3
1000000000000

Output

200000000001

 

题意:做一个汉堡需要B、S、C三种搭配。搭配的方式很多种,但是只想要一种规定的搭配。目前厨房里拥有一定的B、S、C,分别为nb、ns、nc。其次你有一定的钱,可以去商店里买来B、S、C,分别以pb,ps,pc的价格。请问你最多能够做多少个汉堡。

 

题解:

我们采取一种比较贪心的思路,先用完厨房里拥有的B、S、C,然后再出去商店一套一套地买汉堡配料,看看能够买多少份。

 

对的,这道题我挺晚做出来,还是一开始对题意有一丝丝理解错误,然后后面一套一套买汉堡那里没有处理好。

#include <iostream>
#include <string.h>
#include <algorithm>

using namespace std;

string st;
long long  len,B,S,C,ans,ans1,ans2;
long long  bi,si,ci;
long long  pb,ps,pc;
long long  mon;
long long mon_ham;
long long num_ham;

void read_in()
{
    cin>>st;len=st.size();
    for(int i=0;i<len;i++)
    {
        if(st[i]=='B') B++;
        if(st[i]=='S') S++;
        if(st[i]=='C') C++;
    }
    cin>>bi>>si>>ci>>pb>>ps>>pc>>mon;
    mon_ham=S*ps+B*pb+C*pc;
}

long long  take_ham()
{
    long long  b=100000,s=100000,c=100000;
    if(B!=0)  b=bi/B;
    if(S!=0)  s=si/S;
    if(C!=0)  c=ci/C;
    long long  ham=min(min(b,s),c);
    bi-=B*ham;si-=S*ham;ci-=C*ham;
    return ham;
}

bool judge_it()
{
    long long cut=0;
    if(B>bi && B!=0)
        cut+=pb*(B-bi);
    if(S>si && S!=0)
        cut+=ps*(S-si);
    if(C>ci && C!=0)
        cut+=pc*(C-ci);
    if(cut==mon_ham)
        return false;
    if(cut<=mon)
        return true;
    return false;
}

void buy_()
{
    if(B>bi)
    {
        int buy_b=B-bi;
        if(mon>=buy_b*pb)
        {
            bi+=buy_b;
            mon-=buy_b*pb;
        }
    }
    if(S>si)
    {
        int buy_s=S-si;
        if(mon>=buy_s*ps)
        {
            si+=buy_s;
            mon-=buy_s*ps;
        }

    }
    if(C>ci)
    {
        int buy_c=C-ci;
        if(mon>=buy_c*pc)
        {
            ci+=buy_c;
            mon-=buy_c*pc;
        }
    }
    return ;
}

void buy_all()
{
    long long mon_ham=S*ps+B*pb+C*pc;
    long long num_ham=mon/mon_ham; 
    ans+=num_ham;
    mon=mon%mon_ham;
}

int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    read_in();
    ans+=take_ham();
    while(judge_it())
    {
        buy_();
        ans+=take_ham();
    }
    buy_all();
    cout<<ans;
    return 0;
}

 

C题

黑暗爆炸 - 1614

 

Description

FarmerJohn打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务。于是,FJ必须为此向电信公司

支付一定的费用。FJ的农场周围分布着N(1<=N<=1,000)根按1..N顺次编号的废弃的电话线杆,任意两根电话线杆间

都没有电话线相连。一共P(1<=P<=10,000)对电话线杆间可以拉电话线,其余的那些由于隔得太远而无法被连接。

第i对电话线杆的两个端点分别为A_i、B_i,它们间的距离为L_i(1<=L_i<=1,000,000)。数据中保证每对{A_i,B_i

}最多只出现1次。编号为1的电话线杆已经接入了全国的电话网络,整个农场的电话线全都连到了编号为N的电话线

杆上。也就是说,FJ的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话

网络。经过谈判,电信公司最终同意免费为FJ连结K(0<=K<N)对由FJ指定的电话线杆。对于此外的那些电话线,FJ

需要为它们付的费用,等于其中最长的电话线的长度(每根电话线仅连结一对电话线杆)。如果需要连结的电话线

杆不超过K对,那么FJ的总支出为0。请你计算一下,FJ最少需要在电话线上花多少钱。

Input

* 第1行: 3个用空格隔开的整数:N,P,以及K

* 第2..P+1行: 第i+1行为3个用空格隔开的整数:A_i,B_i,L_i

Output

* 第1行: 输出1个整数,为FJ在这项工程上的最小支出。

如果任务不可能完成, 输出-1

Sample Input

5 7 1
1 2 5
3 1 4
2 4 8
3 2 3
5 2 9
3 4 7
4 5 6
输入说明:
一共有5根废弃的电话线杆。电话线杆1不能直接与电话线杆4、5相连。电话
线杆5不能直接与电话线杆1、3相连。其余所有电话线杆间均可拉电话线。电信
公司可以免费为FJ连结一对电话线杆。

Sample Output

4
输出说明:
FJ选择如下的连结方案:1->3;3->2;2->5,这3对电话线杆间需要的
电话线的长度分别为4、3、9。FJ让电信公司提供那条长度为9的电话线,于是,
他所需要购买的电话线的最大长度为4。

Hint

Source

Silver

 

题意:找出从1到n的最短路之中,第k-1大的边。

以后看到这种求最小中的最大,尝试想想二分才行。现在几乎都不会想到二分。

这里用二分,把大于mid的边设为1,然后小于mid的边设为0。跑一遍最短路,看看到点n的时候距离为多少,既是最短路里的大于mid的边有k条,妙呀。

到达不了的情况就是根本去不了n,如果去的了n点的话那就肯定是有答案的。

代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>

using namespace std;

const int INF=0x3f3f3f3f;
int n,m,k,l,r,mid,ans=-1;
int pi,p[1005],to[20005],nex[20005],cost[20005];
int val[1005];
bool vis[1005];
queue<int>q;

void read_into(int u,int v,int c)
{
	pi++; nex[pi]=p[u]; p[u]=pi; to[pi]=v; cost[pi]=c;
}

void read_in()
{
	ios::sync_with_stdio(false),cin.tie(0);
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
	{
		int u,v,c;
		cin>>u>>v>>c;
		read_into(u,v,c);
		read_into(v,u,c);
		r=max(r,c);
	}
}

bool judge_it(int t)
{
	for(int i=1;i<=n;i++)
	  val[i]=INF,vis[i]=false;
	while(!q.empty())
	  q.pop();
	q.push(1); vis[1]=true; val[1]=0;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		vis[u]=false;
		for(int i=p[u],v=to[i];i;i=nex[i],v=to[i])
		{
			if(val[v] > val[u] + (cost[i] > t))
			{
				val[v]=val[u]+ (cost[i]>t);
				if(!vis[v])
				{
					vis[v]=true;
					q.push(v);
				}
			}
		}
	}
	if(val[n] > k)
	  return 0;
	return 1;
}

void work()
{
	while(l<=r)
	{
		mid=(l+r)/2;
		if(judge_it(mid))
		{
			r=mid-1;
			ans=mid;
		}
		else
		  l=mid+1;
		if(val[n]>1000000)
		  break;
	}
	cout<<ans;
}

int main()
{
	read_in();
	work();
	return 0;
}

 

 

D题

UVA - 1619 

Description

Bill is developing a new mathematical theory for human emotions. His recent investigations are dedicated to studying how good or bad days influent people’s memories about some period of life. A new idea Bill has recently developed assigns a non-negative integer value to each day of human life. Bill calls this value the emotional value of the day. The greater the emotional value is, the better the day was. Bill suggests that the value of some period of human life is proportional to the sum of the emotional values of the days in the given period, multiplied by the smallest emotional value of the day in it. This schema reflects that good on average period can be greatly spoiled by one very bad day. Now Bill is planning to investigate his own life and find the period of his life that had the greatest value. Help him to do so.

Input
The input will contain several test cases, each of them as described below. Consecutive test cases are separated by a single blank line.
The first line of the input file contains n — the number of days of Bill’s life he is planning to
investigate (1 ≤ n ≤ 100000). The rest of the file contains n integer numbers a1, a2, . . . , an ranging
from 0 to 106 — the emotional values of the days. Numbers are separated by spaces and/or line breaks.

Output
For each test case, the output must follow the description below. The outputs of two consecutive caseswill be separated by a blank line.
On the first line of the output file print the greatest value of some period of Bill’s life.
On the second line print two numbers l and r such that the period from l-th to r-th day of Bill’s
life (inclusive) has the greatest possible value. If there are multiple periods with the greatest possible value, then print any one of them.

Sample Input
6
3 1 6 4 5 2
1
2
Sample Output
60
3 5
 

题意:

找出一个区间[L,R],有[L,R]中的最小值a使得a*sum[L,R]最大。

 

题解:

这题,怎么说,寒假做过,单调栈模板题,但是当时没有做出来,这次也是。

先说说思路吧,挺简单的,假设我们以i为最小值,那么往左找第一个小于i的数为左边界,右边第一个比他小的数为右边界。这样子就可以找出了n个区间了,然后利用前缀和一个一个枚举。

主要还是在找区间的时候用单调栈,使其时间复杂度为O(n)。

问题就是,可能我就是写单调栈写炸了。

我想只进行一遍单调栈,就把左边第一小和右边第一小找到。但是总是WA。

以后就不要这么贪心了,还是老老实实分开两次单调栈。一次单调栈找一边的第一个出现最小值。

 

代码:

#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>


using namespace std;

int n;
long long a[1000005],sum[1000005];
int l[1000005],r[1000005];

void read()
{
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);//cin>>a[i];
    for(int i=1;i<=n;i++)
        sum[i]=sum[i-1]+a[i];
}

void build_stack()
{
	l[0]=0;a[0]=-1;
    stack<int> sta1;
    sta1.push(0);
    for(int i=1;i<=n;++i)
    {
    	while(a[sta1.top()]>=a[i])
    	  sta1.pop();
    	l[i]=sta1.top()+1;
    	sta1.push(i);
	}
	a[n+1]=-1;r[n+1]=n+1;
	stack<int> sta2;
	sta2.push(n+1);
	for(int i=n;i>=1;--i)
	{
		while(a[sta2.top()]>=a[i])
		  sta2.pop();
		r[i]=sta2.top()-1;
		sta2.push(i);
	}
}

void work()
{
    long long ans=0;
	int L=1,R=1;
    for(int i=1;i<=n;++i)
    {
    	long long  tmp=(sum[r[i]]-sum[l[i]-1]) * a[i];
        if(tmp>ans || (tmp==ans && R-L>r[i]-l[i]))
        {
            ans=tmp;
            L=l[i];R=r[i];
        }
    }
    //cout<<ans<<'\n'<<L<<' '<<R<<'\n';
    printf("%lld\n%d %d\n",ans,L,R);
}

int main()
{
	//ios::sync_with_stdio(false),cin.tie(0);
	int tim=0;
	while(~scanf("%d",&n))//cin>>n
    {
        if(tim!=0)
          cout<<'\n';//printf("\n");
        tim++;
		read();
        build_stack();        
        work();

    }

    return 0;
}

 

全部评论

相关推荐

头像
10-13 18:10
已编辑
东南大学 C++
。收拾收拾心情下一家吧————————————————10.12更新上面不知道怎么的,每次在手机上编辑都会只有最后一行才会显示。原本不想写凉经的,太伤感情了,但过了一天想了想,凉经的拿起来好好整理,就像象棋一样,你进步最快的时候不是你赢棋的时候,而是在输棋的时候。那废话不多说,就做个复盘吧。一面:1,经典自我介绍2,项目盘问,没啥好说的,感觉问的不是很多3,八股问的比较奇怪,他会深挖性地问一些,比如,我知道MMU,那你知不知道QMMU(记得是这个,总之就是MMU前面加一个字母)4,知不知道slab内存分配器-&gt;这个我清楚5,知不知道排序算法,排序算法一般怎么用6,写一道力扣的,最长回文子串反问:1,工作内容2,工作强度3,关于友商的问题-&gt;后面这个问题问HR去了,和中兴有关,数通这个行业和友商相关的不要提,这个行业和别的行业不同,别的行业干同一行的都是竞争关系,数通这个行业的不同企业的关系比较微妙。特别细节的问题我确实不知道,但一面没挂我。接下来是我被挂的二面,先说说我挂在哪里,技术性问题我应该没啥问题,主要是一些解决问题思路上的回答,一方面是这方面我准备的不多,另一方面是这个面试写的是“专业面试二面”,但是感觉问的问题都是一些主管面/综合面才会问的问题,就是不问技术问方法论。我以前形成的思维定式就是专业面会就是会,不会就直说不会,但事实上如果问到方法论性质的问题的话得扯一下皮,不能按照上面这个模式。刚到位置上就看到面试官叹了一口气,有一些不详的预感。我是下午1点45左右面的。1,经典自我介绍2,你是怎么完成这个项目的,分成几个步骤。我大致说了一下。你有没有觉得你的步骤里面缺了一些什么,(这里已经在引导我往他想的那个方向走了),比如你一个人的能力永远是不够的,,,我们平时会有一些组内的会议来沟通我们的所思所想。。。。3,你在项目中遇到的最困难的地方在什么方面4,说一下你知道的TCP/IP协议网络模型中的网络层有关的协议......5,接着4问,你觉得现在的socket有什么样的缺点,有什么样的优化方向?6,中间手撕了一道很简单的快慢指针的问题。大概是在链表的倒数第N个位置插入一个节点。————————————————————————————————————10.13晚更新补充一下一面说的一些奇怪的概念:1,提到了RPC2,提到了fu(第四声)拷贝,我当时说我只知道零拷贝,知道mmap,然后他说mmap是其中的一种方式,然后他问我知不知道DPDK,我说不知道,他说这个是一个高性能的拷贝方式3,MMU这个前面加了一个什么字母我这里没记,别问我了4,后面还提到了LTU,VFIO,孩子真的不会。
走呀走:华子二面可能会有场景题的,是有些开放性的问题了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务