A. Fast Food Restaurant
题目描述:
Tired of boring office work, Denis decided to open a fast food restaurant.
On the first day he made a portions of dumplings, b portions of cranberry juice and c pancakes with condensed milk.
The peculiarity of Denis's restaurant is the procedure of ordering food. For each visitor Denis himself chooses a set of dishes that this visitor will receive. When doing so, Denis is guided by the following rules:
every visitor should receive at least one dish (dumplings, cranberry juice, pancakes with condensed milk are all considered to be dishes);
each visitor should receive no more than one portion of dumplings, no more than one portion of cranberry juice and no more than one pancake with condensed milk;
all visitors should receive different sets of dishes.
What is the maximum number of visitors Denis can feed?
Input
The first line contains an integer t (1≤t≤500) — the number of test cases to solve.
Each of the remaining t lines contains integers a, b and c (0≤a,b,c≤10) — the number of portions of dumplings, the number of portions of cranberry juice and the number of condensed milk pancakes Denis made.
Output
For each test case print a single integer — the maximum number of visitors Denis can feed.
Example
input
7
1 2 1
0 0 0
9 1 7
2 2 3
2 3 2
3 2 2
4 4 4
output
3
0
4
5
5
5
7
思路:有三种不同的菜各a,b,c份,求最多可以组成多少不同的组合。范围比较很小,直接枚举。
#include<bits/stdc++.h>
using namespace std;
int a[4];
int main(){
int T;
cin>>T;
while(T--){
cin>>a[1]>>a[2]>>a[3];
int res=0;
for(int i=1;i<=3;++i){
if(a[i]>0) res++,--a[i];
}
sort(a+1,a+4);
if(a[3]>0&&a[2]>0){
res++;
a[3]--;
a[2]--;
}
if(a[3]>0&&a[1]>0){
res++;
a[3]--;
a[1]--;
}
if(a[2]>0&&a[1]>0){
res++;
a[2]--;
a[1]--;
}
if(a[1]>0&&a[2]>0&&a[3]>0){
res++;
}
cout<<res<<'
';
}
return 0;
}
B. Different Rules
题目描述:
Nikolay has only recently started in competitive programming, but already qualified to the finals of one prestigious olympiad. There going to be n participants, one of whom is Nikolay. Like any good olympiad, it consists of two rounds. Tired of the traditional rules, in which the participant who solved the largest number of problems wins, the organizers came up with different rules.
Suppose in the first round participant A took x-th place and in the second round — y-th place. Then the total score of the participant A is sum x+y. The overall place of the participant A is the number of participants (including A) having their total score less than or equal to the total score of A. Note, that some participants may end up having a common overall place. It is also important to note, that in both the first and the second round there were no two participants tying at a common place. In other words, for every i from 1 to n exactly one participant took i-th place in first round and exactly one participant took i-th place in second round.
Right after the end of the Olympiad, Nikolay was informed that he got x-th place in first round and y-th place in the second round. Nikolay doesn't know the results of other participants, yet he wonders what is the minimum and maximum place he can take, if we consider the most favorable and unfavorable outcome for him. Please help Nikolay to find the answer to this question.
Input
The first line contains an integer t (1≤t≤100) — the number of test cases to solve.
Each of the following t lines contains integers n, x, y (1≤n≤109, 1≤x,y≤n) — the number of participants in the olympiad, the place that Nikolay took in the first round and the place that Nikolay took in the second round.
Output
Print two integers — the minimum and maximum possible overall place Nikolay could take.
Examples
input
1
5 1 3
output
1 3
input
1
6 3 4
output
2 6
思路:
一个人参加程序竞赛,共两轮,第一轮的名次为x,第二轮的名次为y,最终名次为两次名次之和的降序顺序。(注意排名考虑并列,例如有3个人并列第一,则这3个人的名次都是第三)
求这个人最好和最坏的情况下取得的名次。
① 最好的情况:
如果x+y<=n 那么可以将每个人的名次组合为n+1(每个人的两次排名倒过来),那么我们就是第一了;
如果x+y>=n+1 那么我们肯定不会是第一了,那么就让个别人尽量地小,并把在我们前面的人剔除排名,假设有k个人那么剔除后就剩n-k个人,当x+y<=n-k时,我们就可以成为这n-k个人的第一了,k=x+y-n,综合排名为k+1.
② 最差的情况:
考虑让尽可能多的人的综合排名等于x+y.假设此时第一轮的排名是升序的,为1,2,3...x+y-1,那么对应着第二轮的分数为 x+y-1,x+y-2...2,1,综合排名为x+y+1,注意(x+y+1可能大于n)
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
long long n,x,y;
cin>>n>>x>>y;
long long Max=min(x+y-1,n);
long long Min;
if(x+y<=n){
Min=1;
}
else {
Min=min(n,x+y-n+1);
}
cout<<Min<<" "<<Max<<'
';
}
return 0;
}
C1. Skyscrapers (easy version) C2. Skyscrapers (hard version)
题目描述:
This is a harder version of the problem. In this version n≤500000
The outskirts of the capital are being actively built up in Berland. The company "Kernel Panic" manages the construction of a residential complex of skyscrapers in New Berlskva. All skyscrapers are built along the highway. It is known that the company has already bought n plots along the highway and is preparing to build n skyscrapers, one skyscraper per plot.
Architects must consider several requirements when planning a skyscraper. Firstly, since the land on each plot has different properties, each skyscraper has a limit on the largest number of floors it can have. Secondly, according to the design code of the city, it is unacceptable for a skyscraper to simultaneously have higher skyscrapers both to the left and to the right of it.
Formally, let's number the plots from 1 to n. Then if the skyscraper on the i-th plot has ai floors, it must hold that ai is at most mi (1≤ai≤mi). Also there mustn't be integers j and k such that j<iai<ak. Plots j and k are not required to be adjacent to i.
The company wants the total number of floors in the built skyscrapers to be as large as possible. Help it to choose the number of floors for each skyscraper in an optimal way, i.e. in such a way that all requirements are fulfilled, and among all such construction plans choose any plan with the maximum possible total number of floors.
Input
The first line contains a single integer n (1≤n≤500000) — the number of plots.
The second line contains the integers m1,m2,…,mn (1≤mi≤109) — the limit on the number of floors for every possible number of floors for a skyscraper on each plot.
Output
Print n integers ai — the number of floors in the plan for each skyscraper, such that all requirements are met, and the total number of floors in all skyscrapers is the maximum possible.
If there are multiple answers possible, print any of them.
Examples
input
5
1 2 3 2 1
output
1 2 3 2 1
input
3
10 6 8
output
10 6 6
思路:
要在一条公路边上盖左右相邻的大楼,第i座大楼的高度不大于m[i],且每座大楼不能同时比左右两边的大楼矮。求所有楼高和的最大值。
可以发现如果要达到要求,必然有且只有一座大楼比左右两边的所有大楼都高,即左右大楼形成一个金字塔型。对于c1 n比较小,可以直接枚举这个最高的大楼,复杂度为O(n^2)。
c2我们需要O(n)的复杂度。每次线性扫描每座楼得到以这座楼为最高的情况,或者左右求两次,一次我们只得到左边或右边都比他矮的情况,因为对于i作为最高时的最优情况满足的1i是递增,1i-1也是,且也是最优的。所以我们可以考虑使用单调栈,从左向右:栈中递增排列,当栈顶j大于当前栈的最大高度时弹出(因为比m[i]高,即使遍历到后面j保持高度也必然不能形成合法的形状,所以只要记住此时j可保持的最大高度时m[i]即可,所以弹出不会影响后面的结果),直到当前栈顶m[k]<=m[i],那么i答案的就是为k为最高点的情况加上k+1~i都是m[i]。从右边向左同理。
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
long long m[maxn],a[maxn];
long long l[maxn],r[maxn],n;
stack<int> sk;
void solve(){
for(int i=1;i<=n;++i){
while(!sk.empty()&&m[sk.top()]>m[i]) sk.pop();
if(sk.empty()) {
l[i]=m[i]*i;
}
else l[i]=l[sk.top()]+(i-sk.top())*m[i];
sk.push(i);
}
while(!sk.empty()) sk.pop();
for(int i=n;i>=1;--i){
while(!sk.empty()&&m[sk.top()]>m[i]) sk.pop();
if(sk.empty())
r[i]=m[i]*(n-i+1);
else r[i]=r[sk.top()]+(sk.top()-i)*m[i];
sk.push(i);
}
long long id=0,Max=0;
for(int i=1;i<=n;++i){
if(l[i]+r[i]-m[i]>Max){
Max=l[i]+r[i]-m[i];
id=i;
}
}
a[id]=m[id];
for(int i=id-1;i>=1;--i)
a[i]=min(a[i+1],m[i]);
for(int i=id+1;i<=n;++i)
a[i]=min(a[i-1],m[i]);
for(int i=1;i<=n;++i)
cout<<a[i]<<" ";
cout<<'
';
}
int main(){
cin>>n;
for(int i=1;i<=n;++i)
cin>>m[i];
solve();
return 0;
}