鸽了好多场的题解,这场不鸽了.
关键这场我也没打呀
Cue一下队友链接:
核心选手:https://me.csdn.net/qq_43559193
核心选手:https://me.csdn.net/weixin_43916298
目录
比赛链接:https://codeforces.com/contest/1359
A. Berland Poker
题目大意:
题目思路:
Code:
B. New Theatre Square
题目大意:
题目思路:
Code:
C. Mixing Water
题目大意:
题目思路:
Code:
D. Yet Another Yet Another Task
题目大意:
题目思路:
Code:
具体没怎么读,看了看样例和解释,大概理解了个意思,瞎写。
题目大体意思应该是 求一个每人手中小丑牌的最大值 - 其他人中最小值 (大概是这样,我也没读题)
然后就很水了呀:
如果小丑牌小于等于每个人应得的手牌,那么肯定是小丑牌数量。
否则一个人全拿,剩下的平分(上取整),然后求一下答案
/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include
#include
#include
#include
#include
#include
#define debug(x) cout<<#x<<":"<'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);read(m);read(p);
ll temp = n/p;
if(temp>=m) printf("%lld\n",m);
else{
ll diff = m - temp;
printf("%lld\n",temp - ((diff+p-2)/(p-1)));
}
}
return 0;
}
/**
* 10 *
0000 1111
**/
输入n,m,x,y 代表有n*m的矩阵,涂1*1的格子需要x,涂1*2的格子需要y,问最少花费多少使得图中所有的'.'均被染色
首先可以得出 如果2*x <= y ,ans = ‘.’的个数 * x
否则,全涂1 * 2 剩下的涂1,然后可以发现 1*2只可以横着涂,那么就遍历一下就行了
/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include
#include
#include
#include
#include
#include
#define debug(x) cout<<#x<<":"<'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
char str[1005][1005];
vectorv;
int main(){
int T;scanf("%d",&T);
while(T--){
ll x,y;read(n);read(m);
read(x);read(y);
for(int i=1;i<=n;i++) scanf("%s",str[i]+1);
int cot = 0;
for(int i=1;i<=n;i++){
for(int k=1;k<=m;k++){
if(str[i][k]=='.') cot ++;
}
}
if(2*x <= y) printf("%lld\n",1ll*cot*x);
else{
ll ans = 0;
for(int i=1;i<=n;i++){
int cnt = 1;
for(int k=2;k<=m;k++){
if(str[i][k]!=str[i][k-1]){
int res = cnt%2;
if(str[i][k]=='*')
ans+=(cnt/2)*y+res*x;
cnt = 1;
}
else cnt++;
}
int res = cnt%2;
if(str[i][m]=='.')
ans+=(cnt/2)*y+res*x;
}
printf("%lld\n",ans);
}
}
return 0;
}
/**
* 10 *
0000 1111
**/
输入a,b,t,a代表一杯热水的温度,b代表一杯冷水的温度,每次可以倒一杯热水后,再倒一杯冷水,然后..依次类推,最终的温度是这些的平均值,问最少倒几次使得其可以最接近温度t
首先两种情况:
假设热水到了x次
1.假设倒的次数为偶数,那么此时,所以次数为偶数时不需要考虑,只需要记录2的答案就可以
2.假设倒的次数为奇数,那么此时,所以此时无需多言,盲猜具有单调性,直接二分写,发现确实具有单调性...,剩下的就是二分怎么写了。
这题正解应该是解方程吧..二分直接卡死精度了,精度到1e-15才过
/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include
#include
#include
#include
#include
#include
#define debug(x) cout<<#x<<":"<'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
double cal(ll x){
double tempx = x/2+1,tempy = x/2;
return (tempx*n+tempy*m)/(x*1.0);
}
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);read(m);read(p);
if(2*p == n+m) printf("2\n");
else if(n==p) printf("1\n");
else{
int ans = 2;
double diff = abs((double)(n+m)*0.5-(double)p);
ll l = 1, r = 1e9+7;
double ans_left = -1,ans_right = -1;
while(l<=r){
ll mid = (l+r)/2;
double res = cal(2*mid-1);
if(res-p>eps){
ans_right = 2*mid-1;
l = mid+1;
}
else{
ans_left = 2*mid-1;
r = mid-1;
}
}
if(ans_left!=-1)
if(abs(cal(ans_left)-p)-diff
抽象一下:选择一个区间,让这个区间减去当前区间最大值,求这种答案的最大值
经典套路了,直接秒掉就可以了
枚举一下最大值的位置,单调栈维护最大值可控区间,查一下前缀和的最大值最小值,计算答案就可以了。
本着优化算法的初衷,直接把区间查询换成O1查询的st表,124ms跑到起飞。
这题正解的话应该是枚举30个值作为最大值 复杂度30*n 不过st表预处理也就lgn的复杂度 ,复杂度20*n
所以,哪个好写写哪个咯
/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include
#include
#include
#include
#include
#include
#define debug(x) cout<<#x<<":"<'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m;
int st[maxn];
int pre[maxn],cur[maxn];//表示前方可以控制到多少,后方可以控制到多少。
ll num[maxn];
ll st_max[maxn][20],st_min[maxn][20];
ll lg[maxn];
ll f[maxn];
void work()
{
ll cnt=0;
for(int i=1;i<=n;i++)
lg[i]=lg[i/2]+1;
for(int i=0;i<=n;i++)
st_max[i][0]=st_min[i][0]=f[i];
for(int j=1;j<=25;j++)
for(int i=0;i+(1<=num[st[bg]])
bg--;
pre[i]=st[bg];
st[++bg]=i;
}
bg=0;
st[0]=n+1;
for(int i=n;i>=1;i--){
while(bg!=0&&num[i]>=num[st[bg]])
bg--;
cur[i]=st[bg];
st[++bg]=i;
}
for(int i=1;i<=n;i++) pre[i]++,cur[i]--;
}
int main(){
read(n);
for(int i=1;i<=n;i++){
read(num[i]);
f[i] = f[i-1] + num[i];
}
work();
get_min();
ll maxl = 0;
for(int i=1;i<=n;i++){
ll temp = query_max(i,cur[i]) - query_min(pre[i]-1,i-1);
maxl = max(maxl,temp-num[i]);
}
printf("%lld\n",maxl);
return 0;
}
/**
* 10 *
0000 1111
**/
下面看一下E题,哦数论或者组合数学呀,打扰了,争取不鸽你。