蓝桥杯系统:蓝桥杯练习A组省赛/决赛【PREV237】

PREV237:答疑

答疑
题意
n个学生找老师答疑。第i个学生的进入办公室和答疑的时长为 s i + a i s_i+a_i si+ai,答疑完成后在课程群发送消息,然后花 e i e_i ei的时间离开办公室。之后下一个学生进入。求所有学生的发送消息的时刻之和的最小值。
思路
贪心排序。对于学生x和y,假设先x后y,则发送时刻之和为
( s x + a x ) + ( s x + a x + e x + s y + a y ) (s_x+a_x)+(s_x+a_x+e_x+s_y+a_y) (sx+ax)+(sx+ax+ex+sy+ay)
同理,先y后x的发送时刻之和为:
( s y + a y ) + ( s y + a y + e y + s x + a x ) (s_y+a_y)+(s_y+a_y+e_y+s_x+a_x) (sy+ay)+(sy+ay+ey+sx+ax)
则当先x后y更优的适合满足 ( s x + a x + e x ) < ( s y + a y + e y ) (s_x+a_x+e_x)<(s_y+a_y+e_y) (sx+ax+ex)<(sy+ay+ey)。则以此进行排序。
//倒在贪心排序的坑里无数次了,这回终于反应过来了55

#include<bits/stdc++.h> 
#define all(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pll pair<ll,ll>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1.0);
const ll mx = 1e3 + 10;
const ll inf = 100000 + 10;

struct node{
	ll s, a, e;
	bool operator < (const node ob)const{
		return s+a+e < ob.s+ob.a+ob.e;
	}
}nos[mx];
ll n;
void solve(){
	scanf("%lld", &n);
	rep(i,1,n){
		scanf("%lld %lld %lld", &nos[i].s, &nos[i].a, &nos[i].e);
	}
	sort(nos+1,nos+1+n);
	ll ans = 0, ct = 0;
	rep(i,1,n){
		ans += (ct + nos[i].s+nos[i].a);
		ct += (nos[i].s+nos[i].a+nos[i].e);
	}
	printf("%lld\n", ans);
}

int main(){
//	cin.tie(0); 
//	ios::sync_with_stdio(0);
 
	#ifdef LOCAL
	freopen("1.txt", "r", stdin);
	#endif
	solve();
	#ifdef LOCAL
	fclose(stdin);
	#endif
	return 0;
}
PREV234:出租车(太难了放弃)

出租车

PREV231:皮亚诺曲线距离(50%)

皮亚诺曲线距离
题意
如题
思路
dfs求当前点到(0,0)的距离【代码中为(1,1)】。每次dfs把区间划分为9个正方形。然后发现,第二行的正方形其实相对于左下角的正方形x对称,第二列的相对于左下角的正方形y对称。坐标转换,dfs当前正方形内点到起点的距离,+当前正方形之前的正方形的点数(num数组存了之前的同大小的正方形数量)。最后把每层dfs的距离加起来(点数)得到当前点到(0,0)的距离。
根据题目,求出两个点到起点的距离之差。只能过50%的点,估计是k很大的时候没办法处理了。

#include<bits/stdc++.h> 
#define all(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pll pair<ll,ll>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1.0);
const ll mx = 1e6 + 10;

ll b3[200];
ll k, xa, ya, xb, yb;
ll num[4][4]={
	0,0,0,0,
	0,0,1,2,
	0,5,4,3,
	0,6,7,8
};
ll dist(ll level, ll x, ll y){
	if(level == 0) return 1;
	ll edge = b3[level], edge2 = b3[level-1];
	ll xx = (x+edge2-1)/edge2;
	ll yy = (y+edge2-1)/edge2;
//	printf("level:%lld, xx:%lld, yy:%lld, x:%lld, y:%lld\n", 
//		level, xx, yy, x, y);
	x -= (xx-1) * edge2, y -= (yy-1) * edge2;
	if(yy == 2) x = edge2 - x + 1;
	if(xx == 2) y = edge2 - y + 1;
	ll ans = dist(level-1, x, y) + num[xx][yy] * edge2 * edge2;
	return ans;
}

void solve(){
	b3[0] = 1;
	rep(i,1,100) b3[i] = b3[i-1] * 3;
	scanf("%lld", &k);
	scanf("%lld %lld %lld %lld", &xa, &ya, &xb, &yb);
	xa++,ya++,xb++,yb++;
	ll d1 = dist(k, xa, ya);
	ll d2 = dist(k, xb, yb);
	printf("%lld\n", abs(d1-d2));
}
 
int main(){
//	cin.tie(0); 
//	ios::sync_with_stdio(0);
 
	#ifdef LOCAL
	freopen("1.txt", "r", stdin);
	#endif
	solve();
	#ifdef LOCAL
	fclose(stdin);
	#endif
	return 0;
}
PREV67:字串排序(70%)

字串排序
题意
给定数字N,求最短的字符串使逆序对数量为N。如果存在多种方案,选择逆序对最小的方案。
思路
DP。不知道哪里错了。也不想看了。摆……

#include<bits/stdc++.h> 
#define all(x) x.begin(),x.end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pll pair<ll,ll>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const double eps=1e-8;
const double PI=acos(-1.0);
const ll mx = 2e2 + 10;
const ll N = 26;
//maxlen = 156
ll dp[mx][N+10][mx], input;
ll f[mx][N+10];//f[i][k]表示长度i,种类数k的最大逆序对数 
ll query(ll len){//升序 
	rep(i,1,len){//第i个位置 
		rep(k,1,min(i,N)){//选择颜色k 
			dp[i][k][1] = 0;
			if(k == 1)continue;
			//第i-1个位置 颜色k-1 至少一个 最多(i-1)-(k-2)个 
			rep(j,1,i-k+1) 
				dp[i][k][1] = max(dp[i][k][1], dp[i-1][k-1][j]);
			dp[i][k][1] += i-1;
			//第i个位置 颜色k 最多 i-k+1个 
			rep(j,2,i-k+1) 
				dp[i][k][j] = dp[i-1][k][j-1]+i-j;
		}
	}
	ll maxv = 0;
	rep(j,1,len) maxv = max(maxv, dp[len][min(len,N)][j]);
	return maxv;
}
ll getNiXuDui(ll len){
	ll kind = 0;
	rep(k,1,N){
		ll maxv = 0;
		rep(j,1,len) maxv = max(maxv, dp[len][k][j]);
		if(maxv>=input){
			kind = k;
			break;
		}
	}
	rep(i,1,len){
		rep(k,1,kind){
			f[i][k] = 0;
			rep(j,1,len) f[i][k] = max(f[i][k],dp[i][k][j]);
		}
	}
	return kind;
}
void solve(){
	scanf("%lld", &input);
	if(input == 0){//实际上没有这种输入 
		printf("a");
		return; 
	}

	ll zuo = 1, you = 156;
	while(zuo <= you){
		ll mid = (zuo + you)>>1;
		ll q = query(mid);
		if(q >= input) you = mid - 1;
		else zuo = mid + 1;
	}
	ll number = zuo;
	printf("mini Len: %lld\n", number);
	//找到最佳颜色种类数
	query(number); 
	ll kind = getNiXuDui(number);
	printf("mini Color Num: %lld\n", kind);
	//开始搭配
	ll total = number;
	vector<char>ans;
	irep(k,kind,2){//颜色搭配 从大到小 
		rep(num,1,number){//k色数量为num 
			ll nv = num * (number - num) + f[number-num][k-1];
			if(nv >= input){
				input -= num * (number - num);
				number -= num;
				rep(i,1,num) ans.pb((char)('a'+k-1));
				break;
			}
		}
	} 
	ll gs = ans.size();
	rep(i,0,gs-1) printf("%c",ans[i]);
	rep(i,1,total - gs) printf("a");
	puts("");
}

int main(){
//	cin.tie(0); 
//	ios::sync_with_stdio(0);
 
	#ifdef LOCAL
	freopen("1.txt", "r", stdin);
	#endif
	solve();
	#ifdef LOCAL
	fclose(stdin);
	#endif
	return 0;
}
PREV60:回文日期

回文日期
题意
略。
思路
暴力。

#include <bits/stdc++.h>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
//#define LOCAL
using namespace std;
typedef long long ll;
const ll mx = 1e5 + 10;
ll year, month, day;
ll d[13] = {0,
31,28,31,30,31,
30,31,31,30,31,
30,31};
ll ans1[10], ans2[10], s[10];
bool runnian(ll year){
	if(year%400 == 0) return true;
	if(year%100 == 0) return false;
	return year%4 == 0;
}
void nextday(){
	bool r = runnian(year);
	if(r==false || month!=2){
		if(day!=d[month]){
			day++;
		}
		else{
			day=1;
			if(month!=12) month++;
			else month=1,year++;
		}
	}
	else{
		if(day!=29) day++;
		else day++,month++;
	}
}
ll ishuiwen(){
	ll ny = year;
	rep(i,0,3){
		s[4-i]= ny %10;
		ny /= 10;
	}
	s[5]=month/10;
	s[6]=month%10;
	s[7]=day/10;
	s[8]=day%10;
	for(ll l=1,r=8;l<=r;l++,r--){
		if(s[l]!=s[r])return -1;
	}
	ll a = s[1], b = s[2];
	if(s[3]!=a || s[4]!=b) return 0;
	return 1;
}
//ABABBABA

void solve(){
	scanf("%04lld%02lld%02lld", &year,&month,&day);
	bool huiwen=false;
	while(1){
		nextday();
		ll ans = ishuiwen();
		if(ans>=0 && !huiwen){
			huiwen = true;
			memcpy(ans1, s, sizeof s);
		}
		if(ans == 1){
			if(!huiwen) memcpy(ans1, s, sizeof s);
			memcpy(ans2, s, sizeof s);			
			break;
		}
	}
	rep(i,1,8)printf("%lld",ans1[i]);
	puts("");
	rep(i,1,8)printf("%lld",ans2[i]);
	puts("");
}

int main(){
	#ifdef LOCAL
	freopen("1.txt","r",stdin);
	#endif
	solve();
	#ifdef LOCAL
	fclose(stdout);
	#endif
	return 0;
}
PREV56:子串分值

子串分值
题意
略。
思路
求每个字母的贡献

#include <bits/stdc++.h>
#define rep(i,l,r) for(ll i = l; i <= r; i++)
#define irep(i,r,l) for(ll i = r; i >= l; i--)
//#define LOCAL
using namespace std;
typedef long long ll;
const ll mx = 1e5 + 10;
char s[mx];
ll l[mx], r[mx];
void solve(){
	scanf("%s", s+1);
	ll len = strlen(s+1);
	ll ans = 0;
	rep(i,0,25){
		char c = i+'a';
		ll zuo = 0, you = len + 1;
		rep(j,1,len){
			if(s[j]!=c)continue;
			l[j] = zuo;
			zuo = j;
		}
		irep(j,len,1){
			if(s[j]!=c)continue;
			r[j] = you;
			you = j;
		}
		rep(j,1,len){
			if(s[j]!=c)continue;
			ll ln = j-l[j]-1, rn = r[j]-j-1;
			ans += (1+ln) * (1+rn);
		}
	}
	printf("%lld\n", ans);
	
}

int main(){
	#ifdef LOCAL
	freopen("1.txt","r",stdin);
	#endif
	solve();
	#ifdef LOCAL
	fclose(stdout);
	#endif
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值