AtCoder Beginner Contest 366
AtCoder Beginner Contest 366题解
A - Election 2
题意:
\(n\)张票,目前投了\(t\)给高桥, \(a\) 给青木。
问剩余票随便分配,是否都是一个结局。
思路:
将剩下的票全都给同一个人,看看是否局面发生变化
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+100,mod=998244353;
typedef long long ll;
typedef pair<int,int> PII;
int T;
void solve()
{
int a,b,c;
cin>>a>>b>>c;
if(b>a-b||c>a-c) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
signed main()
{
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
T=1;
//cin>>T;99 12 48
while(T--)
{
solve();
}
return 0;
}
B - Vertical Writing
题意:
给定\(n\)个字符串,把这 \(n\)个字符串顺时针旋转90度,输出。
由于字符串长度不一,可能会出现空的情况,前面的
都要替换成*
。
思路:
先将字符串翻转90°,然后记录一下每一行最后一个字符的位置end,在end前的位置如果存在空,则要替换为*
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+100,mod=998244353;
typedef long long ll;
typedef pair<int,int> PII;
int T;
int n;
char op[1010][1010];
int ba[N];
void solve()
{
cin>>n;
for(int i=1;i<=110;i++)
for(int j=1;j<=110;j++)
op[i][j]='*';
int mx=0;
for(int i=1;i<=n;i++)
{
string kk;
cin>>kk;
mx=max(mx,(int)kk.size());
for(int j=0;j<kk.size();j++) op[i][j+1]=kk[j];
}
for(int i=1;i<=mx;i++)
{
for(int j=n;j>=1;j--)
{
if(op[j][i]!='*') ba[i]=j;
}
}
for(int i=1;i<=mx;i++)
{
for(int j=n;j>=ba[i];j--) cout<<op[j][i];
cout<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
T=1;
//cin>>T;99 12 48
while(T--)
{
solve();
}
return 0;
}
C - Balls and Bag Query
题意:
q个操作,分三种。
1 x
放入背包一个球,数字x
2 x
从背包拿出一个球,数字x
3
问背包不同数字球的个数
思路:
模拟即可
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=998244353;
typedef long long ll;
typedef pair<int,int> PII;
int T;
bool st[N];
int cnt[N];
int ans=0;
void solve()
{
int q;
cin>>q;
memset(cnt,0,sizeof cnt);
memset(st,false,sizeof st);
while(q--)
{
int id;
cin>>id;
if(id==1)
{
int x;
cin>>x;
if(!st[x])
{
st[x]=true;
cnt[x]++;
ans++;
}
else
{
cnt[x]++;
}
}
else if(id==2)
{
int x;
cin>>x;
if(cnt[x]==1)
{
cnt[x]=0;
st[x]=false;
ans--;
}
else
{
cnt[x]--;
}
}
else
{
cout<<ans<<endl;
}
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
T=1;
//cin>>T;
while(T--)
{
solve();
}
return 0;
}
D - Cuboid Sum Query
题意:
给定一个正整数 \(N\),以及一个整数 \(A_{x,y,z}\),对于每组三个整数 \((x, y, z)\),满足 \(1 \leq x, y, z \leq N\)。
将给出 \(Q\) 个查询,格式如下,必须按顺序处理。
对于第 \(i\) 个查询 \((1 \leq i \leq Q)\),给定一个整数元组 \((Lx_i, Rx_i, Ly_i, Ry_i, Lz_i, Rz_i)\),使得 \(1 \leq Lx_i \leq Rx_i \leq N\)、\(1 \leq Ly_i \leq Ry_i \leq N\) 和 \(1 \leq Lz_i \leq Rz_i \leq N\)。求:
\(\sum_{x=Lx_i}^{Rx_i} \sum_{y=Ly_i}^{Ry_i} \sum_{z=Lz_i}^{Rz_i} A_{x,y,z}\)
思路:
三维区间求和,考验空间想象能力。
前缀和表达式
:
\(s[i][j][k]=s[i][j][k-1]+s[i][j-1][k]+s[i-1][j][k]-s[i-1][j-1][k]-s[i-1][j][k-1]-s[i][j-1][k-1]+s[i-1][j-1][k-1]+f[i][j][k]\)
\((x1, x2, y1, y2, z1, z2)\)的区间的和为
:
\(s[x2][y2][z2]-s[x1-1][y2][z2]-s[x2][y1-1][z2]-s[x2][y2][z1-1]+s[x2][y1-1][z1-1]+s[x1-1][y2][z1-1]+s[x1-1][y1-1][z2]-s[x1-1][y1-1][z1-1]\)
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10,mod=998244353;
typedef long long ll;
typedef pair<int,int> PII;
int T;
int n,q;
int f[110][110][110];
int s[110][110][110];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int h=1;h<=n;h++)
cin>>f[i][j][h];
memset(s,0,sizeof s);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)for(int k=1;k<=n;k++)
{
s[i][j][k]=s[i][j][k-1]+s[i][j-1][k]+s[i-1][j][k]-s[i-1][j-1][k]+f[i][j][k]-s[i-1][j][k-1]-s[i][j-1][k-1]+s[i-1][j-1][k-1];
}
cin>>q;
while(q--)
{
int x1,x2,y1,y2,z1,z2;
cin>>x1>>x2>>y1>>y2>>z1>>z2;
int ans=s[x2][y2][z2]-s[x1-1][y2][z2]-s[x2][y1-1][z2]-s[x2][y2][z1-1]+s[x2][y1-1][z1-1]+s[x1-1][y2][z1-1]+s[x1-1][y1-1][z2]-s[x1-1][y1-1][z1-1];
cout<<ans<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
T=1;
//cin>>T;
while(T--)
{
solve();
}
return 0;
}
E - Manhattan Multifocal Ellipse
题意:
给定 \(n\) 个二维平面上的点 \((x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)\) 和一个非负整数 \(D\),我们需要计算满足以下条件的整数对 \((x, y)\) 的数量:
\(\sum_{i=1}^n (|x - x_i| + |y - y_i|) \leq D\)
思路:
可以发现x,y坐标是相互独立的,所以我们可以分开处理:对每一个坐标上\([-2e6,2e6]\)上的点\(x_k\),我们可以二分预处理出\(\sum_{i=1}^n(|x_k-x_i|)\)的值,找到第一个比它大的点\(x_a\),那么\(\sum_{i=1}^n(|x_k-x_i|)\)=\(\sum_{i=1}^{a-1} (x_a-x_i)\)+\(\sum_{i=a}^{n}(x_i-x_a)\),记为\(ra[i]\).将得到的值进行排序,要求\(ra+rb<=D\)的个数,可以双指针\(O(n)\)求出.
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=998244353;
typedef long long ll;
typedef pair<int,int> PII;
int T;
int n,d;
int x[N],y[N];
int sa[N];
int sb[N];
vector<int> ra;
vector<int> rb;
void solve()
{
cin>>n>>d;
for(int i=1;i<=n;i++) cin>>x[i]>>y[i];
sort(x+1,x+1+n);
sort(y+1,y+1+n);
sa[0]=sb[0]=0;
for(int i=1;i<=n;i++) sa[i]=sa[i-1]+x[i],sb[i]=sb[i-1]+y[i];
for(int i=-2e6;i<=2e6;i++)
{
int l=0,r=n+1;
while(l+1!=r)
{
int mid=(l+r)/2;
if(x[mid]>i) r=mid;
else l=mid;
}
int p=(2*l-n)*i+sa[n]-sa[l]-sa[l];
ra.push_back(p);
}
for(int i=-2e6;i<=2e6;i++)
{
int l=0,r=n+1;
while(l+1!=r)
{
int mid=(l+r)/2;
if(y[mid]>i) r=mid;
else l=mid;
}
int p=(2*l-n)*i+sb[n]-sb[l]-sb[l];
rb.push_back(p);
}
sort(ra.begin(),ra.end());
sort(rb.begin(),rb.end());
int j=rb.size()-1;
int ans=0;
for(auto i : ra)
{
while(j>=0)
{
if(i+rb[j]>d) j--;
else
{
ans+=(j+1);
break;
}
}
if(j<0) break;
}
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
T=1;
//cin>>T;
while(T--)
{
solve();
}
return 0;
}
F - Maximum Composition
题意:
给定N个线性函数\(f_1,f_2,...,f_n\),其中\(f_i(x)=A_ix+B_i\)
求最大的\(f_{p_1}(f_{p_2}(...f_{p_k}(1)...))\)值
思路:
只考虑两个函数\(f_1\)和\(f_2\):\(f_1=a_1x+b_1\)和\(f_2=a_2x+b_2\),如何选择位置使得值最大。
\(f_1(f_2(1))=a_1(a_2+b_2)+b_1=a_1a_2+a_1b_2+b_1\)
\(f_2(f_1(1))=a_2(a_1+b_1)+b_2=a_2a_1+a_2b_1+b_2\)
假设\(f_1(f_2(1))<f_2(f_1(1))\),那么有\(a_1b_2+b_1<a_2b_1+b_2\),整理得\(\frac{a_1-1}{b_1}<\frac{a_2-1}
{b_2}\)
即如果\(\frac{a_i-1}{b_i}\)更大,我们就考虑把它放在外面。所以我们可以对\(\frac{a_i-1}{b_i}\)排序,从\(n\)个函数中取出\(k\)个,使得值最大,类似于01背包的写法
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10,mod=998244353;
typedef long long ll;
typedef pair<int,int> PII;
int T;
int n,k;
struct node
{
int a;
int b;
}x[N];
bool cmp(node x,node y)
{
return (y.a-1)*x.b>(x.a-1)*y.b;
}
int dp[N];
void solve()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>x[i].a>>x[i].b;
sort(x+1,x+1+n,cmp);
dp[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=k;j>=1;j--)
{
dp[j]=max(dp[j],x[i].a*dp[j-1]+x[i].b);
}
}
cout<<dp[k]<<endl;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
T=1;
//cin>>T;
while(T--)
{
solve();
}
return 0;
}