A - Air Conditioner
代码
signed main()
{
int x;
cin >> x;
if(x >= 30) cout << "Yes" << endl;
else cout << "No" << endl;
}
B - Distance
分析
题意:给一堆点,问到原点距离在k以内的点的个数。
思路:a * a + b * b <= k * k 不开根号,避免丢失精度。
代码
#include <bits/stdc++.h>
#include <sstream>
using namespace std;
#define endl "\n"
#define int long long
signed main()
{
int n, d, cnt = 0;
cin >> n >> d;
d = d * d;
for(int i = 1; i <= n; i ++)
{
int a, b;
cin >> a >> b;
if(a * a + b * b <= d) cnt ++;
}
cout << cnt << endl;
}
C - Repsept
分析
题意:给你一个k,问你7,77,777,7777…中是否有一个数是k的倍数,如果有,输出这个数的位数,否则输出-1。
思路:大数取余。模拟除法得到余数的过程,让777…的位数每次增加一位,然后除以k,如果除尽,输出这个数的位数,否则输出-1。
借一张图:
https://blog.csdn.net/qq_43690454/article/details/108859923
代码
#include <iostream>
using namespace std;
const int N = 1e6+1000;
int mod;
int main(void)
{
cin >> mod;
int f = 0, sum = 0, ans = 0;
for(int i = 0; i < N; i ++)
{
sum = (sum * 10 + 7) % mod;
if(sum % mod == 0)
{
f = 1, ans = i;
break;
}
}
if(f) cout << ans + 1 << endl;
else cout << -1 << endl;
return 0;
}
D - Alter Altar
分析
思维 or 双指针
题意:给定字符串s s只包括两种字符’R’和’W’ 'W’不能出现在’R’的左边
很**的,想了好久都没整出来(因为懒得模拟,懒得动手,得改 )。
思路1:统计字符串中R的个数,记为cntR,可以推断最终结果一定是“RRRWWWW”的样子,所以只需要将区间[1,cntR]中的W和R交换就行,因此答案就是[1,cntR]中W的个数。大佬的思路,妙不可言。
代码1
#include <bits/stdc++.h>
using namespace std;
char a[200010];
int posw[200010], posr[200010];
int main()
{
int n;
cin >> n;
cin >> (a+1);
int cntr = 0;
for(int i = 1; i <= n; i ++)
{
if(a[i] == 'R') cntr ++;
}
int ans = 0;
for(int i = 1; i <= cntr; i ++)
{
if(a[i] == 'W') ans ++;
}
cout << ans << endl;
}
思路2:其实就是一个双指针,从两端开始把右边出现的R和左边出现的W交换即可。
代码2
#include <bits/stdc++.h>
using namespace std;
char a[200010];
int posw[200010], posr[200010];
int main()
{
int n;
cin >> n;
int cntw = 0, cntr = 0;
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
if(a[i] == 'W') posw[cntw++] = i;
else posr[cntr++] = i;
}
int ans = 0;
int l = 1, r = n;
while (l < r)
{
while(a[l] == 'R') l ++;
while(a[r] == 'W') r --;
if(l < r) swap(a[l], a[r]),ans ++;
}
cout << ans << endl;
}
E - Logs
分析
简单二分
题意:N个圆木,问切最多K次,最小的最大值是什么,题眼最小的最大值或者最大的最小值通常都是二分。
思路:最多砍K刀,并且保证每个原木最大长度为mid,如果K次可以实现把每一根原木都控制在<=mid,那么这个方案就是可行的。
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5+10;
ll a[N];
ll n, k;
bool check(ll mid)
{
ll kk = k;
// 一共K刀, 保证mid是最大值
for(int i = 1; i <= n; i ++)
{
if(a[i] <= mid) continue;
kk -= ceil(a[i]/mid);
if(kk < 0) break;
}
if(kk >= 0) return true;
else return false;
}
signed main()
{
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
// 排不排序都行
sort(a+1,a+1+n);
// 左边界为0会RE,比如l=0,r=1,l+r>>1=0,check函数中0不能做分母
// ll l = 0, r = a[n];
ll l = 1, r = a[n];
while (l < r)
{
ll mid = (l + r) / 2;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l << endl;
}
F - Range Set Query
分析
树状数组+离线处理
题意:给n个颜色,询问L~R区间内出现了几种颜色。
例如 1 3 6 3 1 2, [2, 4] 出现的颜色有3 6 1,共三种染色,答案为3
思路:(很简单耐心看完)这题可以使用可持久化线段树,代码太多了不考虑了。使用树状数组就是求前缀和,那么问题来了: 如何求前缀和的时候不重复计算多次出现的颜色,保证重复的颜色贡献只有1?
我的做法是开pos数组记录这个颜色上一次出现的位置,每次有重复颜色时,就把上一次出现的颜色的贡献清零,只计算最后一次出现的颜色的贡献。但这时候需要保证需要离线处理询问,将其按右端点R排序,每一次查询的时候,重复元素的贡献值不会出现在右端点R的右边。
再使用一个额外的pos数组记录上一次出现的重复颜色的下标就行,使用树状数组将上一次重复出现的位置-1,最新的位置+1,query函数得到的前缀和一定是每个颜色最多一次贡献。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+10;
int pos[N], c[N], a[N], nowPos = 1;
int n, q;
struct Node
{
int first, second, id, ans;
} qs[N];
int query(int x)
{
int res = 0;
for(;x;x-=x&(-x)) res += c[x];
return res;
}
void insert(int x, int d)
{
for(;x<=n;x+=x&(-x)) c[x] += d;
}
bool cmp(Node a, Node b)
{
return a.second < b.second;
}
bool cmp2(Node a, Node b)
{
return a.id < b.id;
}
signed main()
{
cin >> n >> q;
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
}
for(int i = 1; i <= q; i ++)
{
cin >> qs[i].first >> qs[i].second;
qs[i].id = i;
}
sort(qs+1, qs+1+q, cmp);
for(int i = 1; i <= q; i ++)
{
for(int j = nowPos; j <= qs[i].second; j ++)
{
if(pos[a[j]] == 0)
{
insert(j, 1);
pos[a[j]] = j;
}
else
{
insert(pos[a[j]], -1);
insert(j, 1);
pos[a[j]] = j;
}
}
nowPos = qs[i].second + 1;
// 这样直接输出是不对的啊
// 排序之后就不是原来的询问顺序了
// cout << query(qs[i].second) - query(qs[i].first-1) << endl;
qs[i].ans = query(qs[i].second) - query(qs[i].first-1);
}
sort(qs+1, qs+1+q, cmp2);
for(int i = 1; i <= q; i ++)
{
cout << qs[i].ans << endl;
}
return 0;
}