首页 > 其他分享 >AtCoder Beginner Contest 353 - VP 记录

AtCoder Beginner Contest 353 - VP 记录

时间:2024-11-13 18:22:27浏览次数:1  
标签:AtCoder ch Beginner Contest int pos long Problem Sigma

Preface

这次比赛蛮简单的,就是黄题有点多,少了区分度。

而且 Sigma Problem Another Sigma Problem Yet Another Sigma Problem 是什么奇妙的题目名称?

            Sigma Problem
    Another Sigma Problem
Yet Another Sigma Problem

\(\texttt{\scriptsize Yet \footnotesize Another \normalsize Sigma Problem}\)

真好玩

F 题题面看上去很可做,有点迷惑人,实际上对我来说 G 题才是更能做的(也确实能一眼做法)。

A - Buildings

点击查看代码
#include<cstdio>
using namespace std;

const int N=105;
int n,h[N];

int main()
{
	scanf("%d",&n);
	int pos=-1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&h[i]);
		if(h[i]>h[1]&&pos==-1) pos=i;
	}
	printf("%d\n",pos);
	return 0;
}

B - AtCoder Amusement Park

高桥出场。

点击查看代码
#include<cstdio>
using namespace std;

const int N=105;
int n,k,a[N];

int main()
{
	scanf("%d%d",&n,&k);
	int rest=0,ans=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		if(rest<a[i]) rest=k,ans++;
		rest-=a[i];
	}
	printf("%d\n",ans);
	return 0;
}

C - Sigma Problem

好家伙,卡我二十多分钟,而且两次都莫名其妙 TLE 一个点 代码挂了,不怪 AtCoder。

将原数列排序,后每个数与前面的数组合的情况分为两部分:一部分的数与当前数相加小于 \(10^8\),另一部分大于等于 \(10^8\)。对于后一部分,需要对每个和都减去一个 \(10^8\)。

两个部分的交界点可以用二分或双指针维护,我用的是双指针。

算上排序的时间复杂度是 \(O(n \log n)\)。

#include<cstdio>
#include<algorithm>
using namespace std;

const int N=3e5+5,P=1e8;
int n;
long long a[N],sum[N],ans;

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	sort(a+1,a+n+1);
	int pos=-1;
	for(int i=1;i<=n;i++)
	{
		ans+=a[i]*(i-1)+sum[i-1];
		if(a[i]+a[i-1]>=P)
		{
			if(pos==-1) pos=i-1;
			while(pos>=0 && a[pos]+a[i]>=P) pos--;
			ans-=1ll*(i-pos-1)*P;
		}
		sum[i]=sum[i-1]+a[i];
	}
	printf("%lld\n",ans);
	return 0;
}

D - Another Sigma Problem

比上一道更简单,设 \(a_i\) 有 \(l\) 位,与前面的数组合相当于前面的数乘以了 \(10^l\)。将前面的所有数的和乘以 \(10^l\) 再加上 \(a_i\) 被算了 \((i-1)\) 次,就是其与前面组合的答案,对每一个 \(a_i\) 全部加起来即可。

#include<cstdio>
using namespace std;

namespace IO{
template<typename TYPE> void read(TYPE &x)
{
	x=0; bool neg=false; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')neg=true;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}
	if(neg){x=-x;} return;
}
template<typename TYPE> void write(TYPE x)
{
	if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;}
	static int sta[55];int statop=0; while(x){sta[++statop]=x%10;x/=10;}
	while(statop){putchar('0'+sta[statop--]);} return;
}
template<typename TYPE> void write(TYPE x,char ch){write(x);putchar(ch);return;}
} using namespace IO;

const int N=2e5+5,P=998244353;
int n;
long long a[N],sum[N],ans;
long long ten[25];

int main()
{
	ten[0]=1;
	for(int i=1;i<=15;i++)
		ten[i]=ten[i-1]*10%P;
	read(n);
	for(int i=1;i<=n;i++)
	{
		read(a[i]);
		int l=0; long long t=a[i];
		while(t) l++,t/=10;
		ans=(ans+sum[i-1]*ten[l]%P+a[i]*(i-1)%P)%P;
		sum[i]=(sum[i-1]+a[i])%P;
	}
	write(ans,'\n');
	return 0;
}

E - Yet Another Sigma Problem

这是道原题,准确来说,这是这道题的简化版,也不知道为什么有些人没做起。

建立字典树,记录每个节点被经过的次数,然后每次在字典树中匹配字符串时把路径上的经过次数值加起来就是它与前面所有字符串的 LCP(最长公共前缀)之和。

#include<cstdio>
#include<cstring>
using namespace std;

const int N=3e5+5;
int n; char str[N];
long long ans;

int trie[N][30],idx;
int cnt[N];
void Insert(char s[])
{
	int p=0,len=strlen(s);
	for(int i=0;i<len;i++)
	{
		char ch=s[i]; int num=ch-'a'+1;
		if(!trie[p][num]) trie[p][num]=++idx;
		p=trie[p][num];
		cnt[p]++;
	}
	return;
}
long long Query(char s[])
{
	int p=0,len=strlen(s);
	long long res=0;
	for(int i=0;i<len;i++)
	{
		char ch=s[i]; int num=ch-'a'+1;
		if(!trie[p][num]) break;
		p=trie[p][num];
		res+=cnt[p];
	}
	return res;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",str);
		ans+=Query(str);
		Insert(str);
	}
	printf("%lld\n",ans);
	return 0;
}

G - Merchant Takahashi

一眼 DP,做法也很模板,几乎也是一眼(好像是因为我之前做过类似的题)。

先考虑暴力 DP,设 \(f_{i,j}\) 表示前 \(i\) 轮走到城镇 \(j\) 的最大收益,那么有:

\[f_{i,j} = \max_{k=1}^{n} \{f_{j,k} - c \times \lvert j-k \rvert\} \]

第一维可以压掉,变成:

\[f_i = \max_{j=1}^{n} \{ f_j - c \times \lvert i-j \rvert \} \]

时间复杂度 \(O(nm)\),过不掉此题,考虑优化。

对于每一个位置 \(i\),把 \(f_j\) 分为 \(j \le i\) 和 \(j \ge i\) 两部分(不要管这两部分有重叠的问题)。左边部分收益随距离的变化量(路费)分别为:

\[-(i-1)c, -(i-2)c, \cdots, -2c, -c, 0 \]

转化一下,得到:

\[(1-i)c, (2-i)c, \cdots, ((i-2)-i)c, ((i-1)-i)c, (i-i)k \]

容易发现,在上述 \((x-y)c\) 的形式中,\(x\) 为左侧其它位置各自的下标,\(y\) 为所求位置下标。

所以对于左侧的 \(f\),只需要维护 \(f_j+jc\)(JC!)的最大值即可,在 \(i\) 左侧求得这个的最大值以后,再减去 \(ic\) 就是向左走的最大收益。

同理,右侧只要把求左侧的过程翻转一下就可以了。路费分别为:

\[0, -c, -2c, \cdots, -(n-i-1)c, -(n-i)c \]

对于右边,维护 \(f_j+(n-j+1)c\),在 \(i\) 右侧找最大值再减去 \((n-i+1)c\) 就是向右走的最大收益。

对左右两边取最大值即为 \(f_i\)。

维护左右侧的最大值可以用最大值树状数组,一个找前缀最大值,一个找后缀最大值。

注意一定要将相关变量初始化为极小值(除了 \(1\)),代表只能从 \(1\) 出发。

#include<cstdio>
#include<algorithm>
using namespace std;

namespace IO{
template<typename TYPE> void read(TYPE &x)
{
	x=0; bool neg=false; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')neg=true;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}
	if(neg){x=-x;} return;
}
template<typename TYPE> void write(TYPE x)
{
	if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;}
	static int sta[55];int statop=0; while(x){sta[++statop]=x%10;x/=10;}
	while(statop){putchar('0'+sta[statop--]);} return;
}
template<typename TYPE> void write(TYPE x,char ch){write(x);putchar(ch);return;}
} using namespace IO;

const int N=2e5+5,M=2e5+5;
int n,m;
long long k,t[M],p[M];
long long ans;

struct BIT{ //前缀最大值树状数组
	long long c[M];
	void Init()
	{
		for(int i=0;i<=n;i++)
			c[i]=-1e18;
		return;
	}
	inline int lowbit(int x){return x&-x;}
	void update(int x,long long y)
	{
		for(;x<=n;x+=lowbit(x))
			c[x]=max(c[x],y);
		return;
	}
	long long query(int x)
	{
		long long res=-1e18;
		for(;x;x-=lowbit(x))
			res=max(res,c[x]);
		return res;
	}
}fl;
struct BIT_r{ //后缀最大值树状数组
	long long c[M];
	void Init()
	{
		for(int i=0;i<=n;i++)
			c[i]=-1e18;
		return;
	}
	inline int lowbit(int x){return x&-x;}
	void update(int x,long long y)
	{
		for(;x;x-=lowbit(x))
			c[x]=max(c[x],y);
		return;
	}
	long long query(int x)
	{
		long long res=-1e18;
		for(;x<=n;x+=lowbit(x))
			res=max(res,c[x]);
		return res;
	}
}fr;

long long f[N];
int main()
{
	read(n),read(k); read(m);
	fl.Init(),fr.Init();
	for(int i=1;i<=n;i++) f[i]=-1e18;
	f[1]=0; fl.update(1,k),fr.update(1,n*k);
	for(int i=1;i<=m;i++)
	{
		read(t[i]),read(p[i]);
		f[i]=max(
			fl.query(t[i])-t[i]*k,
			fr.query(t[i])-(n-t[i]+1)*k
		)+p[i];
		fl.update(t[i],f[i]+t[i]*k),
		fr.update(t[i],f[i]+(n-t[i]+1)*k);
		ans=max(ans,f[i]);
	}
	write(ans,'\n');
	return 0;
}

标签:AtCoder,ch,Beginner,Contest,int,pos,long,Problem,Sigma
From: https://www.cnblogs.com/jerrycyx/p/18544378

相关文章

  • AtCoder 板刷记录
    话说为啥这些场都没有G题的说[ABC200F]MinflipSummation显然的策略是把全部都是一个数的段变成全不都是另一个数,然后考虑进行dp设一个dp[i][0/1][0/1]表示一下前i个字符中奇偶性为j填的数是k时j的总和然后直接做就行了,需要矩阵快速幂加速一下[ABC201F]Insert......
  • AtCoder Beginner Contest 378 题解
    AtCoderBeginnerContest378题解比赛链接A-Pairing贪心#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;voidShowball(){vector<int>a(5);for(inti=0;i<4;i++){intx;cin>>x;a[x]++;......
  • AtCoder Beginner Contest 356 - VP记录
    A-SubsegmentReverse点击查看代码#include<cstdio>#include<numeric>#include<algorithm>usingnamespacestd;constintN=105;intn,a[N],l,r;intmain(){ scanf("%d%d%d",&n,&l,&r); iota(a+1,a+n+1,1); reverse(a+l,......
  • The 2024 ICPC Asia East Continent Online Contest (I) G
    Link:TheMedianoftheMedianoftheMedian考虑二分答案,对中位数进行二分,每次去判断是否比中位数大即可。我们钦定了一个中位数\(x\),对于\(\{a\}\)数组,若\(a_i\gex\),则令\(a_i=1\),否则\(a_i=0\),这样有一个好处,我们只关心\(1\)和\(0\)的数量,就可以知道中位数......
  • AtCoder Beginner Contest 379
    这次又是倒在了t5,没救了。ABC379A-Cyclic难度:红#include<bits/stdc++.h>usingnamespacestd;intmain(){chara,b,c;cin>>a>>b>>c;cout<<b<<c<<a<<''<<c<<a<<b;return0;}B-......
  • C - Sowing Stones(python解)-atcoder
    C-SowingStones**(python解)-atcoder原题链接:C-SowingStones问题分析:每个包含石头的单元格X[i]中有A[i]个石头。我们需要确保每个单元格从1到N最终都有1个石头。思路:可用的石头总数必须等于单元格的总数。即需要N个石头,但只有ΣA[i](其中A[i]是单元格......
  • AtCoder Beginner Contest 379
    A-Cyclic题意输入\(3\)个连续字符\(a,b,c\),输出另外两种顺序。思路模拟。代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongtypedefpair<int,int>pii;constintmxn=1e6+5;voidsolve(){ chara,b,c; cin......
  • Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解
    总体情况A-Cyclic题意给你一个三位整数\(N\),其中每个数字都是介于\(1\)和\(9\)之间的整数。设\(a\),\(b\),\(c\)分别是\(N\)的百位、十位和个位数。打印一个按此顺序排列\(b\),\(c\),\(a\)所组成的整数,以及一个按此顺序排列\(c\),\(a\),\(b\)所组成......
  • The 2022 ICPC Asia Hangzhou Regional Programming Contest
    Preface久违地线下训练,没想到前年的比赛还有没打过的漏网之鱼这场由于一个中期题G被看出来是去年暑假前集训做过的原,导致题目难度跨度有点大最后一共出了8题,J几何的思路其实出的大差不差了,赛后改了改就过了A.ModuloRuinstheLegend首先转化下题意,令\(A=n,B=\frac{n......
  • atcoder DP做题笔记
    [ABC163E]ActiveInfants题意:给定长度为\(n(n\le2\times10^3)\)的序列\(a\),重排使得\(a_x\times|x-p_x|\)之和最大。独立完成。从大到小地考虑\(a_i\),贪心地使得\(|x-p_x|\)最大。那么\(p_x\)要么在最左,要么在最右。因此在左边和右边形成了一坨前/后缀,然后......