Rank 379/3037. AC 7/12.
A. 小沙の好客
题意
给定
思路
二分前缀和。
或者使用
时间复杂度:
对应AC代码
import java.io.*;
import java.math.*;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(), q = scanner.nextInt();
long[] a = new long[n + 1];
for(int i=1;i<=n;i++) a[i] = scanner.nextInt();
Arrays.sort(a);
long[] sum = new long[n + 1];
for(int i=1;i<=n;i++) sum[i] = sum[i - 1] + a[i];
while(q -- > 0){
int k = scanner.nextInt(), x = scanner.nextInt();
int l = 1, r = n, mid;
while (l <= r) {
mid = (l + r) >> 1;
if (a[mid] <= x) l = mid + 1;
else r = mid - 1;
}
if(r >= k) System.out.println(sum[r] - sum[r - k]);
else System.out.println(sum[r]);
}
}
}
二分别忘了咋写啊草
B. 小沙の博弈
题意
两个很聪明的人进行博弈,每个人面前有无数多个格子,每个格子可以放无限个石子。给定
胜负取决于两人面前格子的字典序大小,字典序小的人获胜。
思路
显然,要让字典序小,聪明的人绝对会只拿
先手没有必胜策略。
时间复杂度:
对应AC代码
import java.io.*;
import java.math.*;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println(n % 2 == 0 ? "win-win!" : "Yaya-win!");
}
}
你这先手怎么这么菜啊.jpg
C. 小沙の不懂
题意
对于两个可能含有前导
注:映射操作指 $ti=p{a_i}$
思路
分类讨论题。
我们设给定的数为
若
和 的长度相同:若它们完全一致,那么 和 相等;否则无法判断。 若
的长度大于 ,那么我们先考虑将 和 右对齐后多出来的部分 ,因为考虑到前导 ,若 中有至少两个不同的数字,那么 对应的原数部分一定有一个数不是 ,那么 的位数一定比 多, ;否则,我们设 中唯一出现的数为 ,那么我们只要判断 剩下部分的最高位和 的最高位是否都是 即可,如果是的话就无法判断,否则 依旧大于 。 反之同理。
时间复杂度:懒得分析
对应AC代码
import java.io.*;
import java.math.*;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String a = scanner.next(), b = scanner.next();
int la = a.length(), lb = b.length();
if(a.equals(b)) System.out.println("=");
else if(la > lb){
char p = a.charAt(0);
boolean f = false;
for(int i=1;i<la-lb;i++) {
if(a.charAt(i) != p){
f = true;
break;
}
}
if(f) System.out.println(">");
else{
if(b.charAt(0) == p && a.charAt(la - lb) != p) System.out.println(">");
else System.out.println("!");
}
}
else if(lb > la){
char p = b.charAt(0);
boolean f = false;
for(int i=1;i<lb-la;i++) {
if(b.charAt(i) != p){
f = true;
break;
}
}
if(f) System.out.println("<");
else{
if(a.charAt(0) == p && b.charAt(lb - la) != p) System.out.println("<");
else System.out.println("!");
}
}else System.out.println("!");
}
}
题目太阅读理解了
D. 小沙の赌气
题意
两个人打游戏,打下一关需要满足前一关通关。对于每一个人,每轮会给定
思路
对于一个人的通关情况,我们可以用一个数
在每次
于是乎,我们比较
时间复杂度:
对应AC代码
import java.io.*;
import java.math.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[][] x = new int[n][2], y = new int[n][2];
for(int i=0;i<n;i++) x[i] = new int[]{scanner.nextInt(), scanner.nextInt()};
for(int i=0;i<n;i++) y[i] = new int[]{scanner.nextInt(), scanner.nextInt()};
AtomicInteger num1 = new AtomicInteger(0), num2 = new AtomicInteger(0);
PriorityQueue<int[]> q1 = new PriorityQueue<>(Comparator.comparingInt(o -> o[0])),
q2 = new PriorityQueue<>(Comparator.comparingInt(o -> o[0]));
for(int i=0;i<n;i++){
work(x[i], num1, q1);
work(y[i], num2, q2);
System.out.println(num1.get() == num2.get() ? "win_win!" : (num1.get() > num2.get() ? "sa_win!" : "ya_win!"));
System.out.println(Math.abs(num1.get() - num2.get()));
}
}
private static void work(int[] now, AtomicInteger num, PriorityQueue<int[]> q){
if(now[0] > num.get() + 1){
q.offer(now);
}else{
int r = Math.max(num.get(), now[1]);
while(!q.isEmpty()){
int[] c = q.peek();
if(c[0] <= r + 1){
q.poll();
r = Math.max(r, c[1]);
}else break;
}
num.set(r);
}
}
}
woc怎么这么简单
E. 小沙の印章
待补充
F. 小沙の串串
题意
给定一个字符串
思路
因为考虑到字典序的贪心性:只要比较第一个不相同的字符即可判断字典序的大小。
也就是说,我们只需让前几位尽可能大即可。
那么,若两个字母之间存在比他们小的数,我们就可以考虑维护一个
对于字符串的输出,我们可以用三个字符串分开存储,最后拼接在一起。
更具体地说,我们可以从大到小枚举所有字母,并从前往后枚举
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100010;
queue<int> q[30];
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, k;
cin >> n >> k;
string s, s1, s2, s3;
cin >> s;
for(int i=0;i<n;i++){
q[s[i] - 'a'].emplace(i);
}
int l = 0, l1 = 0;
while(k){
for(int i=25;i>=0;i--){
while(!q[i].empty() && q[i].front() < l) q[i].pop();
if(!q[i].empty() && q[i].front() <= l + k){
int t = q[i].front();
q[i].pop();
k -= t - l;
while(l < t) s2 += s[l ++];
s1 += s[l ++];
l1 ++;
break;
}
}
if(l == n) break;
}
for(int i=l;i<n;i++) s3 += s[i];
while(!s1.empty() && k){
s2 += s1[l1 -- - 1];
s1.pop_back();
k --;
}
sort(s2.rbegin(), s2.rend());
cout << (s1 + s3 + s2);
}
草,这题很好听懂但很难说明白思路
G. 小沙の编码
待补充
H. 小沙の店铺
题意
给定初始价格
思路
纯模拟打卡题
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
#define int long long
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int x, y, k, n, t;
cin >> x >> y >> k >> n >> t;
int cnt = 0, tot = 0, now = 0;
while("If the world love me"){
cnt ++;
tot += n * (x + now / k * y);
now += n;
if(tot >= t) {
break;
}
if(n - 1 <= 0){
cnt = -1;
break;
}
n --;
}
cout << cnt;
}
差点打卡题卡了一会儿
I. 小沙の金银阁
题意
给定
思路
乱猜,从
时间复杂度:
对应AC代码
import java.io.*;
import java.math.*;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong(), m = scanner.nextLong();
//1e15约2e50
if(n > 51 || m < (1L << (n - 1))) System.out.println(-1);
else{
long[] out = new long[60];
for(int i=1;i<n;i++){
out[i] = m / 2 + m % 2;
m /= 2;
}
System.out.printf("%d ", m);
for(int i=(int)n-1;i>0;i--) System.out.printf("%d ", out[i]);
}
}
}
正常一点的题解
乱猜就完事了((
J. 小沙の最短路
待补充
K. 小沙の抱团 easy
题意
给定
思路
要让操作被所有人认可,那么应该满足少数服从多数的原则,因而我们可以以
暴力模拟求操作数即可
时间复杂度:
对应AC代码
import java.io.*;
import java.math.*;
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long n = scanner.nextLong();
long cnt = 0;
while(n > 2){
cnt ++;
n = n / 2 + 1;
}
System.out.println(cnt);
}
}
怎么感觉还是乱猜((
L. 小沙の抱团 hard
题意
在上一题的基础上,指令是给定的,且每个指令有对应的代价,但每个指令可以被重复使用。输出让剩余人数最少的最小代价。
思路
考虑到代价以及重复使用,我们可以用类似于完全背包的写法。
当剩余
对于当前剩余
当没有一个指令可行的时候,或者剩余
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100010, M = 510, inf = 10000000000ll;
struct sb{
int b, x;
}o[M];
int dp[N];
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for(int i=0;i<m;i++) cin >> o[i].b >> o[i].x;
for(int i=2;i<n;i++) dp[i] = inf;
bool ok = false;
for(int i=n;i>2;i--){
if(dp[i] == inf) continue;
bool f = true;
for(int j=0;j<m;j++){
int mod = i % o[j].x;
if(mod == 0 || i <= o[j].x) continue;
dp[i - mod] = min(dp[i - mod], dp[i] + o[j].b);
f = false;
}
if(f) {
cout << dp[i];
ok = true;
break;
}
}
if(!ok) cout << dp[2];
}
简单的dp
- 本文链接 https://floating-ocean.github.io/blog_old/posts/1889400236/
- 版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!