打到了 R a n k 33 Rank\ 33 Rank 33,还是不错的。
第一次顺顺畅畅没有WA地AK了一场ABC,写篇题解纪念一下……
Solution
T1
直接模拟即可。
T2
分别枚举每个点并用已给的公式算出其与原点的距离,然后统计距离不大于 k k k的点数即可。
建议用 l o n g d o u b l e long\ double long double存储。
T3
暴力即可,考虑如何快速判断 k k k个 1 1 1时其是否能被 n n n整除。
我们可以维护一个值,即当前这么多 1 1 1组成的数模 n n n的值。考虑在末尾加上一个 1 1 1后,原数 x x x变为了 10 x + 1 10x+1 10x+1,那么模数也乘 10 10 10加 1 1 1,即模数可以 O ( 1 ) O(1) O(1)维护。
当模数为 0 0 0时显然满足要求,立即输出并结束即可。注意当位数达到一定量的时候,应跳出循环输出 − 1 -1 −1。
T4
显然,满足要求的条件是,左边清一色的 R R R且右边清一色的 W W W。
于是,我们算出 W W W的数量为 c n t cnt cnt,在原字符串的最后 c n t cnt cnt位中数出不为 W W W的字符数量,即为答案。
注意,这种做法的正确性在于,在后面 c n t cnt cnt位中,每遇到一个不是 W W W的字符就应当与前面 n − c n t n-cnt n−cnt个字符中一个不为 R R R的字符交换,此时满足要求且决策最优。
T5
首先,思考这样一个问题: 如果一个块的长度为 x x x,每次把它劈成两个块,最终要求任何一个块的长度均不超过 l e n len len,求最少劈的次数。
我们可以贪心地操作,即对于长木块,每次都劈掉一块长度为 l e n len len的,直到满足要求,此时决策最优且劈的次数为 ⌈ a b ⌉ − 1 \lceil \frac a b \rceil -1 ⌈ba⌉−1。
回到原题,可以发现是一道有单调性的二分题(最小值最大, 最大值最小这种字眼应该很敏感吧)。我们每次判断: 能否让块的最大值最终不大于 m i d mid mid且劈的次数不多于 k k k次。判断的方式就是判断 ∑ i = 1 n ( ⌈ a i m i d ⌉ − 1 ) \sum_{i=1}^n (\lceil \frac {a_i} {mid} \rceil -1) ∑i=1n(⌈midai⌉−1)的值是否超过了 k k k,其中前者表示,分别考虑每个块至少要被劈的次数使得其产生的新块中不含大于 m i d mid mid的块。
时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)。
T6
莫队解法的时间复杂度为 O ( n n ) O(n \sqrt n) O(nn),经过简单的计算,发现 50000 × 500000 ≈ 3.6 × 1 0 8 50000×\sqrt {500000}≈3.6×10^8 50000×500000≈3.6×108,以及它约为 2 2 2的常数,在 2000 m s 2000ms 2000ms的时限下易被卡,所以果断放弃莫队。
此时,我们可以将询问按右端点排序,维护一个序列 b b b,其中 b i b_i bi表示第 i i i个位置当前对答案的贡献。显然,如果我们目前扫到了第 9 9 9个位置,第 4 4 4个位置与它的值一样;那么,对于之后所有右端点在 9 9 9号位置及 9 9 9号位置之后的询问中,第 4 4 4个位置均不可能产生贡献。同时,第 9 9 9个位置暂时产生了 1 1 1的贡献。
于是,我们同时维护一个数组 l a s t last last, l a s t i last_i lasti记录下 i i i这个数上一次出现的位置。若目前扫到了第 i i i个位置,根据之前说的,要将第 i i i个位置的贡献值加 1 1 1;若 l a s t a i last_{a_i} lastai(上一次出现的位置)的值不是 0 0 0,即更新过,那么 l a s t a i last_{a_i} lastai位置的贡献值要扣除 1 1 1。一次对于 [ l , r ] [l,r] [l,r]的询问,答案显然是 ∑ i = l r b i \sum_{i=l}^r b_i ∑i=lrbi,其中 b i b_i bi记录下了第 i i i个位置的贡献。
发现 b b b数组涉及到单点修改以及区间查询,可以轻松用树状数组来维护。我们另外再维护一个指针 j j j,指向马上需要解决的一个询问,如果该询问解决了就 j + + j++ j++,跳到下一个询问。最后注意,我们先前已将询问按右端点进行了排序,最终输出要还原顺序。
时间复杂度 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)。
Code
T1
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n;
signed main()
{
cin>>n;
if (n>=30) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
T2
#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
int n,d,ans=0;
double x,y;
signed main()
{
cin>>n>>d;
for (int i=1;i<=n;i++)
{
cin>>x>>y;
double len=sqrt(x*x+y*y);
if (len<=d) ans++;
}
cout<<ans<<endl;
return 0;
}
T3
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,ii=0,now=0;
signed main()
{
cin>>n;
while (ii<=80000000)
{
ii++;
now=(now*10+7)%n;
if (now==0) return cout<<ii<<endl,0;
}
cout<<-1<<endl;
return 0;
}
T4
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,cnt=0,ans=0;
char a[200005];
signed main()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=n;i++)
{
if (a[i]=='W') cnt++;
}
for (int i=n-cnt+1;i<=n;i++)
{
if (a[i]!='W') ans++;
}
cout<<ans<<endl;
return 0;
}
T5
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,k,ans=1e9+7;
int a[200005];
inline int up(int aa,int bb)
{
if (aa%bb==0) return aa/bb;
else return (aa/bb)+1;
}
bool check(int len)//check函数
{
int tot=0;
for (int i=1;i<=n;i++) tot=tot+up(a[i],len)-1;
if (tot<=k) return true;
else return false;
}
int Binary_search(int l,int r)//递归式二分写法
{
if (l==r||l+1==r)
{
if (check(l)) ans=min(ans,l);
if (check(r)) ans=min(ans,r);
return ans;
}
int mid=(l+r)>>1;
if (check(mid))
{
ans=min(ans,mid);
return Binary_search(l,mid);
}
else return Binary_search(mid+1,r);
}
signed main()
{
cin>>n>>k;
for (int i=1;i<=n;i++) cin>>a[i];
cout<<Binary_search(1,1e9)<<endl;
return 0;
}
T6
#include <bits/stdc++.h>
using namespace std;
int n,tmp,j=1;
int a[1000005],tree[2000005],last[1000005],ans[1000005];
struct node
{
int rt,l,r;
}q[1000005];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while (ch<'0'||ch>'9')
{
if (ch=='-') w=-w;
ch=getchar();
}
while (ch>='0'&&ch<='9')
{
s=(s<<1)+(s<<3)+(ch^'0');
ch=getchar();
}
return s*w;
}
bool cmp(node x,node y)
{
return x.r<y.r;
}
inline int lowbit(int k)
{
return k&(-k);
}
inline void change(int rt,int num)
{
while (rt<=n)
{
tree[rt]+=num;
rt+=lowbit(rt);
}
}
inline int query(int r)
{
int tot=0;
while (r>=1)
{
tot+=tree[r];
r-=lowbit(r);
}
return tot;
}
signed main()
{
cin>>n;
for (int i=1;i<=n;i++) a[i]=read();
cin>>tmp;
for (int i=1;i<=tmp;i++) q[i].l=read(),q[i].r=read(),q[i].rt=i;
sort(q+1,q+tmp+1,cmp);
for (int i=1;i<=n;i++)
{
change(i,1);
if (last[a[i]]) change(last[a[i]],-1);
while (i==q[j].r&&j<=tmp) ans[q[j].rt]=query(q[j].r)-query(q[j].l-1),j++;
last[a[i]]=i;
}
for (int i=1;i<=tmp;i++) cout<<ans[i]<<endl;
return 0;
}