(AtCoder Beginner Contest 330) 题解

一、前言

有一次做出 6 6 6 道题,痴心妄想 梦想能够稳定 6 6 6 题。

二、题解

言归正传,开始讲题。

第 A 题 Buildings

很简单的一道题,按照模拟即可。——有趣的东西:我为什么吃罚时?因为 y d yd yd 翻译出锅了。(把"左边数第一个"翻译成"左边的一个")

代码:

#include <bits/stdc++.h>
using namespace std;
int a[110];
int main(){
	int n; cin>>n;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		if (i!=1&&a[i]>a[1]){
			cout<<i; return 0;
		}
	}cout<<-1;
} 

第 B 题 AtCoder Amusement Park

也是一道语法题。可以设定 s u m sum sum 为当前排队人数。如果剩余座位不够,就清空,然后在加上人数即可。

代码:

#include <bits/stdc++.h>
using namespace std;
int sum=0,cnt=0;
int main(){
	int n,x,k; cin>>n>>k;
	while (n--){
		cin>>x; //cout<<sum<<"\n";
		if (sum+x>k) sum=0,cnt++;
		sum+=x;
	}cout<<cnt+1;
} 

第 C 题 Sigma Problem

题目说 不要对答案取余

我们可以发现:答案是所有任意两个数加起来的和 - 需要取余的数对数 × 1 0 8 \times10^8 ×108

可以使用二分或双指针解决问题。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[300010],n;
signed main(){
	cin>>n; int sum=0;
	for (int i=1; i<=n; i++) cin>>a[i]; 
	sort(a+1,a+n+1);
	int r=n+1,ans=0;
	for (int l=1; l<=n; l++){
		if (l>=r) r++;
		while (l<r-1&&a[l]+a[r-1]>=100000000) r--;
		ans-=100000000*(n-r+1); ans+=a[l]*(l-1)+sum; sum+=a[l];
	}cout<<ans;
} 

第 D 题 Another Sigma Problem

又一个求和问题(下面左边的加法表示拼接)。

A + B = A × l o g 10 B + B A+B=A\times log_{10}B+B A+B=A×log10B+B

可以使用前缀和解决问题。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mod 998244353
int a[300010],n;
int ask(int x){
	int ans=1;
	while (x) x/=10,ans*=10;
	return ans;
}signed main(){
	cin>>n; int sum=0,ans=0,sumx=0;
	for (int i=1; i<=n; i++) cin>>a[i]; 
	for (int i=n; i>=1; i--){
		ans=(ans+sum+sumx*a[i]%mod)%mod;
		sum+=a[i]; sumx+=ask(a[i]);
		sum%=mod; sumx%=mod;
	}cout<<ans;
} 

第 E 题 Yet Another Sigma Problem

又双叒叕是一道求和问题。

我们可以把一个长度为 5 5 5 的共同最长前缀拆成 5 5 5 个共同前缀(前缀的前缀还是前缀)。

如何求共同前缀的个数?可以使用 M a p Map Map 记录前缀字符串。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
string s[300010];
map <string,int> mp;
signed main(){
	int n,ans=0; cin>>n;
	for (int i=1; i<=n; i++){
		cin>>s[i]; string now="";
		for (int j=0; j<s[i].size(); j++){
			now.push_back(s[i][j]);
			ans+=mp[now]; mp[now]++;
		}
	}cout<<ans;
} 

TLE!怎么办?

智商不够,数据结构来凑!

M a p Map Map 挂掉了,看来只有 T r i e Trie Trie 了!(详见算法笔记)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
string s[300010];
int tr[300010][26],tot;
int num[300010];
signed main(){
	int n,ans=0; cin>>n;
	for (int i=1; i<=n; i++){
		cin>>s[i]; int id=0;
		for (int j=0; j<s[i].size(); j++){
			int to=s[i][j]-'a';
			if (!tr[id][to]){
				tr[id][to]=++tot;
			}id=tr[id][to];
			ans+=num[id]; num[id]++;
		}
	}cout<<ans;
} 

第 G 题 Merchant Takahashi

题目说,有 n n n 次活动,每次活动都在一个点上举行。参加活动会赚钱,移动到相邻的点会花路费。

可以使用 D p Dp Dp

int dp[i];//dp[i]表示在i点最多能赚到多少钱

d p i = d p j + w j − ∣ i − j ∣ × c dp_{i}=dp_{j}+w_{j}-|i-j|\times c dpi=dpj+wjij×c

很显然,超时。那么可以使用线段树进行优化。

代码:

#include <bits/stdc++.h>
using namespace std;
#define mid (l+r)/2
#define ls(n) 2*n
#define rs(n) 2*n+1
#define int long long
int a[800010],b[800010],m;
struct Seg_tree{
	void change(int now){
		a[now]=max(a[ls(now)],a[rs(now)]);
		b[now]=max(b[ls(now)],b[rs(now)]);
	}void update(int now,int l,int r,int id,int val){
		if (l==r){
			a[now]=val+id*m,b[now]=val-id*m; 
			return ;
		} if (id<=mid) update(ls(now),l,mid,id,val);
		else update(rs(now),mid+1,r,id,val);
		change(now);
	}int query1(int now,int l,int r,int ql,int qr){
		if (ql<=l&&r<=qr) return a[now];
		if (qr<=mid) return query1(ls(now),l,mid,ql,qr);
		if (ql>mid) return query1(rs(now),mid+1,r,ql,qr);
		return max(query1(ls(now),l,mid,ql,mid),query1(rs(now),mid+1,r,mid+1,qr));
	}int query2(int now,int l,int r,int ql,int qr){
		if (ql<=l&&r<=qr) return b[now];
		if (qr<=mid) return query2(ls(now),l,mid,ql,qr);
		if (ql>mid) return query2(rs(now),mid+1,r,ql,qr);
		return max(query2(ls(now),l,mid,ql,mid),query2(rs(now),mid+1,r,mid+1,qr));
	}
}t; 
signed main(){
	int n,k,mx=0; cin>>n>>m>>k;
	for (int i=1; i<=n; i++) t.update(1,1,n,i,-(i-1)*m);
	for (int i=1; i<=k; i++){
		int id,k; cin>>id>>k;
		int l=max(1ll,id-k/m),r=min(n,id+k/m);
		int num=max(t.query1(1,1,n,1,id)-id*m,t.query2(1,1,n,id,n)+id*m)+k;
		t.update(1,1,n,id,num); mx=max(mx,num);
	}cout<<mx;
	return 0;
}
  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值