AtCoder Beginner Contest 366题解
A - Election 2
题意:
nnn张票,目前投了ttt给高桥, aaa 给青木。
问剩余票随便分配,是否都是一个结局。
思路:
将剩下的票全都给同一个人,看看是否局面发生变化
代码:
#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
题意:
给定nnn个字符串,把这 nnn个字符串顺时针旋转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
题意:
给定一个正整数 NNN,以及一个整数 Ax,y,zA_{x,y,z}Ax,y,z,对于每组三个整数 (x,y,z)(x, y, z)(x,y,z),满足 1≤x,y,z≤N1 \leq x, y, z \leq N1≤x,y,z≤N。
将给出 QQQ 个查询,格式如下,必须按顺序处理。
对于第 iii 个查询 (1≤i≤Q)(1 \leq i \leq Q)(1≤i≤Q),给定一个整数元组 (Lxi,Rxi,Lyi,Ryi,Lzi,Rzi)(Lx_i, Rx_i, Ly_i, Ry_i, Lz_i, Rz_i)(Lxi,Rxi,Lyi,Ryi,Lzi,Rzi),使得 1≤Lxi≤Rxi≤N1 \leq Lx_i \leq Rx_i \leq N1≤Lxi≤Rxi≤N、1≤Lyi≤Ryi≤N1 \leq Ly_i \leq Ry_i \leq N1≤Lyi≤Ryi≤N 和 1≤Lzi≤Rzi≤N1 \leq Lz_i \leq Rz_i \leq N1≤Lzi≤Rzi≤N。求:
∑x=LxiRxi∑y=LyiRyi∑z=LziRziAx,y,z\sum_{x=Lx_i}^{Rx_i} \sum_{y=Ly_i}^{Ry_i} \sum_{z=Lz_i}^{Rz_i} A_{x,y,z}∑x=LxiRxi∑y=LyiRyi∑z=LziRziAx,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]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]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)(x1, x2, y1, y2, z1, z2)(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]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]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
题意:
给定 nnn 个二维平面上的点 (x1,y1),(x2,y2),…,(xn,yn)(x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)(x1,y1),(x2,y2),…,(xn,yn) 和一个非负整数 DDD,我们需要计算满足以下条件的整数对 (x,y)(x, y)(x,y) 的数量:
∑i=1n(∣x−xi∣+∣y−yi∣)≤D\sum_{i=1}^n (|x - x_i| + |y - y_i|) \leq D∑i=1n(∣x−xi∣+∣y−yi∣)≤D
思路:
可以发现x,y坐标是相互独立的,所以我们可以分开处理:对每一个坐标上[−2e6,2e6][-2e6,2e6][−2e6,2e6]上的点xkx_kxk,我们可以二分预处理出∑i=1n(∣xk−xi∣)\sum_{i=1}^n(|x_k-x_i|)∑i=1n(∣xk−xi∣)的值,找到第一个比它大的点xax_axa,那么∑i=1n(∣xk−xi∣)\sum_{i=1}^n(|x_k-x_i|)∑i=1n(∣xk−xi∣)=∑i=1a−1(xa−xi)\sum_{i=1}^{a-1} (x_a-x_i)∑i=1a−1(xa−xi)+∑i=an(xi−xa)\sum_{i=a}^{n}(x_i-x_a)∑i=an(xi−xa),记为ra[i]ra[i]ra[i].将得到的值进行排序,要求ra+rb<=Dra+rb<=Dra+rb<=D的个数,可以双指针O(n)O(n)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个线性函数f1,f2,...,fnf_1,f_2,...,f_nf1,f2,...,fn,其中fi(x)=Aix+Bif_i(x)=A_ix+B_ifi(x)=Aix+Bi
求最大的fp1(fp2(...fpk(1)...))f_{p_1}(f_{p_2}(...f_{p_k}(1)...))fp1(fp2(...fpk(1)...))值
思路:
只考虑两个函数f1f_1f1和f2f_2f2:f1=a1x+b1f_1=a_1x+b_1f1=a1x+b1和f2=a2x+b2f_2=a_2x+b_2f2=a2x+b2,如何选择位置使得值最大。
f1(f2(1))=a1(a2+b2)+b1=a1a2+a1b2+b1f_1(f_2(1))=a_1(a_2+b_2)+b_1=a_1a_2+a_1b_2+b_1f1(f2(1))=a1(a2+b2)+b1=a1a2+a1b2+b1
f2(f1(1))=a2(a1+b1)+b2=a2a1+a2b1+b2f_2(f_1(1))=a_2(a_1+b_1)+b_2=a_2a_1+a_2b_1+b_2f2(f1(1))=a2(a1+b1)+b2=a2a1+a2b1+b2
假设f1(f2(1))<f2(f1(1))f_1(f_2(1))<f_2(f_1(1))f1(f2(1))<f2(f1(1)),那么有a1b2+b1<a2b1+b2a_1b_2+b_1<a_2b_1+b_2a1b2+b1<a2b1+b2,整理得a1−1b1<a2−1b2\frac{a_1-1}{b_1}<\frac{a_2-1}
{b_2}b1a1−1<b2a2−1
即如果ai−1bi\frac{a_i-1}{b_i}biai−1更大,我们就考虑把它放在外面。所以我们可以对ai−1bi\frac{a_i-1}{b_i}biai−1排序,从nnn个函数中取出kkk个,使得值最大,类似于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;
}