ACM团队周赛题解(3)

940和822两套div.2

老规矩

#define MAXN 1000000+5
#define MOD 1000000007
#define PI (acos(-1.0))
#define EPS 1e-6
#define MMT(s,a) memset(s, a, sizeof s)
#define GO(i,a,b) for(int i = (a); i < (b); ++i)
#define GOE(i,a,b) for(int i = (a); i <= (b); ++i)
#define OG(i,a,b) for(int i = (a); i > (b); --i)
#define OGE(i,a,b) for(int i = (a); i >= (b); --i)


A - Points on the line(940A)

题意:问最少删除几个数字,使得剩余数字的 最大值   -   最小值 < = m;

思路:思维逆向,求符合题意的最多数字

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[105]={0};
 4 int main(){
 5     int n,d,cnt=-9999999;
 6     cin>>n>>d;
 7     for(int i=0;i<n;i++){
 8         cin>>a[i];
 9     }
10     sort(a,a+n);
11     for(int i=0;i<n;i++){
12         for(int j=0;j<n;j++){
13             if(a[j]-a[i]<=d) cnt=max(cnt,j-i+1);
14         }
15     }
16     cout<<n-cnt<<endl;
17     return 0;
18 }

B - Our Tanya is Crying Out Loud

题意:从n走到1,两种走法,从n走到n-1,花费a;从n走到n/k,花费b,问最小花费

思路:最开始还想成BFS了,不需要BFS,因为每次都是从n往1走,只需要对比一下下一步两种花费哪种最小就行了。特判一下k==1的情况。

 1 int main(){
 2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
 3     cin>>n>>k>>a>>b;
 4     if(k == 1){
 5         cout << (n-1)*a << endl;
 6     }
 7     else{
 8         ll ans = 0;
 9         while(n > 1){
10             if(n%k){
11                 int m = n%k;
12                 n -= m;
13                 if(n<1)
14                     ans += a*(m-1);
15                 else
16                     ans += a*m;
17             }
18             else{
19                 int m = n/k;
20                 if((n-m)*a < b)
21                     ans += (n-m)*a;
22                 else
23                     ans += b;
24                 n = m;
25             }
26         }
27         cout << ans << endl;
28     }
29     return 0;
30 }

C - Phone Numbers

题意:给你一个长度为n的字符串,然后让你构造一个长度为m的字符串,只能用n中的字符,可重复,输出m的全排列中字典序比n大的第一个。方便理解,我解释一下第一个样例,n = abc,用这个字符串中的元素构成的长度为3的字符串有很多,比如

aaa, aab, aac, aba, abb, abc, aca, acb.......,然后会发现比abc大的第一个就是aca,所以输出aca。

思路:先分两种情况

当n < m时,这时候只需要在n字符串的后面加m-n个最小字符就行了,因为这就是字典序比n字符串大的第一个字符串。

当n >= m时,首先Hash一下n字符串,这时候我们只需要在n字符串中选取m长度的字符串,然后对这个字符串进行+1操作,也就是把字符串看成k进制数,通过前面的Hash表,进行+1,这样就保证了得到的字符串为m长度,而且是大于n字符串的第一个字符串。

 1 map<char,int> Hsh;
 2 map<int,char> Exhsh;
 3 int k;
 4 char ch1,ch2;
 5
 6 void gethash(string s){
 7     string ss(s);
 8     s.erase(unique(s.begin(),s.end()),s.end());
 9     sort(s.begin(),s.end());
10     ch1 = s[0];
11     ch2 = s[s.size()-1];
12     int len = s.size();
13     GO(i,0,len){
14         Hsh[s[i]] = i;
15         Exhsh[i] = s[i];
16     }
17     //cout << num << endl;
18 }
19
20 int main(){
21     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
22     int n,m;
23     string s;
24     cin>>n>>m>>s;
25     if(m > n){
26         cout << s;
27         sort(s.begin(),s.end());
28         ch1 = s[0];
29         GO(i,n,m){
30             cout << ch1;
31         }
32         cout << endl;
33     }
34     else{
35         gethash(s);
36         string ss = s.substr(0,m);
37         int flag = 0;
38         OGE(i,m-1,0){
39             if(i == m-1){
40                 if(ss[i] < ch2){
41                     ss[i] = Exhsh[Hsh[ss[i]]+1];
42                     flag = 0;
43                 }
44                 else{
45                     ss[i] = ch1;
46                     flag = 1;
47                 }
48             }
49             else if(!flag)
50                 break;
51             else{
52                 if(ss[i] < ch2){
53                     ss[i] = Exhsh[Hsh[ss[i]]+1];
54                     flag = 0;
55                 }
56                 else{
57                     ss[i] = ch1;
58                     flag = 1;
59                 }
60             }
61         }
62         cout << ss << endl;
63     }
64
65     return 0;
66 }

D - Alena And The Heater

题意就是给你一串a,一串b,然后满足下面关系式

  • ai, ai - 1, ai - 2, ai - 3, ai - 4 > r 而且 bi - 1 = bi - 2 = bi - 3 = bi - 4 = 1时,bi = 0
  • ai, ai - 1, ai - 2, ai - 3, ai - 4 < l 而且 bi - 1 = bi - 2 = bi - 3 = bi - 4 = 0时, bi = 1
  • 其他情况bi = bi - 1

然后就是让你去找一对满足题意的 l 和 r 。

思路:按照题目的要求,不断缩进l和r的范围即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=100000+10;
 4 const int INF=1e+9;
 5 const int NINF=-1e+9;
 6 int a[maxn],b[maxn];
 7 string s;
 8 int l,r;
 9 int main(){
10     int n;
11     cin>>n;
12     l=NINF,r=INF;
13     for(int i=0;i<n;i++){
14         cin>>a[i];
15     }
16     cin>>s;
17     for(int i=0;i<s.size();i++){
18         b[i]=s[i]-‘0‘;
19     }
20     for(int i=4;i<n;i++){
21         if(b[i]==1&&b[i-1]==0&&b[i-2]==0&&b[i-3]==0&&b[i-4]==0){
22             l=max(l,max(a[i]+1,max(a[i-1]+1,max(a[i-2]+1,max(a[i-3]+1,a[i-4]+1)))));
23      }
24         else if(b[i]==0&&b[i-1]==1&&b[i-2]==1&&b[i-3]==1&&b[i-4]==1){
25             r=min(r,min(a[i]-1,min(a[i-1]-1,min(a[i-2]-1,min(a[i-3]-1,a[i-4]-1)))));
26         }
27     }
28     cout<<l<<" "<<r<<endl;
29     return 0;
30 }

F - I‘m bored with life

题意:求GCD(a!,b!);

思路:GCD(a!,b!) = min(a!,b!) = (min(a,b))!;

 1 ll f(int n){
 2     if(n == 1)
 3         return 1;
 4     return n*f(n-1);
 5 }
 6
 7 int main(){
 8     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
 9     int a,b;
10     cin>>a>>b;
11     int n = min(a,b);
12     cout << f(n) << endl;
13     return 0;
14 }

G - Crossword solving

题意:就是当把某个字符换成?就代表可以匹配任何字符,问要使得a串在b串中匹配到,最少需要变几个位置,并输出位置;

思路:暴力找a在b每一个位置需要变换几个字符,并存下位置,然后输出最小变换即可。

#define PB push_back

 1 int main(){
 2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
 3     int n,m;
 4     int minn = INT_MAX,ii;
 5     vector<int> q[1005];
 6     string s1,s2;
 7     int num[1005] = {0};
 8     cin>>m>>n;
 9     cin>>s1>>s2;
10     GOE(i,0,n-m){
11         GO(j,0,m){
12             if(s1[j] != s2[i+j]){
13                 num[i]++;
14                 q[i].PB(j+1);
15             }
16         }
17     }
18     GOE(i,0,n-m){
19         if(num[i] < minn){
20             minn = num[i];
21             ii = i;
22         }
23     }
24     cout << minn << endl;
25     for(auto &it:q[ii]){
26         cout << it << ‘ ‘;
27     }
28     cout << endl;
29
30     return 0;
31 }

H - Hacker, pack your bags!

题意:给你一堆时间开始点和结束点,以及花费,问要k小时需要的最小花费,时间不能重叠。

思路:先对所有时间点排序,然后遍历每个时间点的,例如对于第i个,连续时间为x,则去找k-x时间是否存在且满足题意,跟新最小花费,同时用另一个数组维护每个时间段的最小花费。这里排序利用了Tuple的特性所以不需要重构比较函数

#define PB push_back
#define MP make_pair
#define MT make_tuple

 1 vector<tuple<int,int,int>> op;
 2
 3 int N, X;
 4 int L[210000], R[210000], cost[210000];
 5
 6 int dp[210000];
 7 int ans = -1;
 8
 9 int main(){
10     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
11     cin>>N>>X;
12     GO(i,0,N){
13         cin>>L[i]>>R[i]>>cost[i];
14         op.PB(MT(L[i], 0, i));
15         op.PB(MT(R[i], 1, i));
16     }
17     sort(op.begin(), op.end());
18     int len = op.size();
19     GO(i,0,len){
20         int o = get<1>(op[i]), ind = get<2>(op[i]);
21         if(o == 0){   //如果是开始时间点
22             int dur = R[ind] - L[ind] + 1, nec = X - dur;
23             if(nec < 0 || dp[nec] == 0)   //如果x-d这段时间不存在
24                 continue;
25             if(ans == -1 || ans > dp[nec] + cost[ind])  //更新花费
26                 ans = dp[nec] + cost[ind];
27         }
28         else{    //如果是结束时间点
29             int dur = R[ind] - L[ind] + 1;
30             if(dp[dur] == 0 || dp[dur] > cost[ind])  //如果这个时间没有使用或者有更小的花费,更新花费
31                 dp[dur] = cost[ind];
32         }
33     }
34     cout << ans << endl;
35     return 0;
36 }

原文地址:https://www.cnblogs.com/xenny/p/9716714.html

时间: 2024-10-09 12:14:32

ACM团队周赛题解(3)的相关文章

ACM团队周赛题解(2)

拉了CF583和CF486的两套div2题目 还是先贴宏定义部分 #define MAXN 1000000+5#define MOD 1000000007#define PI (acos(-1.0))#define EPS 1e-6#define MMT(s,a) memset(s, a, sizeof s)#define GO(i,a,b) for(int i = (a); i < (b); ++i)#define GOE(i,a,b) for(int i = (a); i <= (b);

2016 年宁波工程学院第七届ACM校赛题解报告

2016 年宁波工程学院第七届ACM校赛题解报告 本题解代码直接为比赛代码,仅供参考. A,B,C,D,G,H,J,K,L,M 来自 Ticsmtc 同学. F 来自 Gealo 同学. E,I 来自Alex 学长. Promblem A :    Two Sum 时间限制: 1 Sec  内存限制: 64 MB 题目描述: 给出n个数,另外给出?个整数S,判断是否可以从中取出2个数,使得这两个数的和是S. 输入: 第?行有个整数T(1 <= T <= 10),代表数据组数. 对于每组数据,第

Leetcode 第174场周赛 题解

Leetcode 第174场周赛 题解 方阵中战斗力最弱的 K 行 签到题,统计一下每行的军人数量,然后设置一下排序规则即可. 时间复杂度 \(O(nlogn)\) typedef long long ll; typedef double db; #define _for(i,a,b) for(int i = (a);i < b;i ++) #define _rep(i,a,b) for(int i = (a);i > b;i --) #define INF 0x3f3f3f3f3f3f3f3

Leetcode 第175场周赛 题解(完结)

Leetcode 第175场周赛 题解 检查整数及其两倍数是否存在 数据范围小的可怜,\(O(n^2)\) 解法可行.如果范围大一点,可以先进行排序然后遍历每一个数进行二分查找,时间复杂度 \(O(nlogn)\) 代码是平方解法. typedef long long ll; typedef double db; #define _for(i,a,b) for(int i = (a);i < b;i ++) #define _rep(i,a,b) for(int i = (a);i > b;i

ACM团队招新赛题解

标程代码全部为C语言编写.代码中的#if LOCAL_ 至#endif为本地一些调试内容,可以忽略. Xenny的A+B(1)[容易][签到] 签到题,做不出的话可能你有点不太适合ACM了. Xenny的A+B(2)[容易][签到] 也没什么好说的,用一个循环控制输入的次数就行了 Xenny的A+B(3)[困难][模拟] 这是本次比赛最难的题目,用意在于赛后你们看见此题题解可以开拓一下思维方式,不要局限于中学的思维,要掌握计算机. 乍一看这题没法做,怎么去存A和B两个这么大的数字,但我们可以用数

第三次周赛题解【并查集 KMP DFS BFS 快速幂】

问题 A: 一道签到题 时间限制: 2 Sec  内存限制: 128 MB 提交: 63  解决: 28 [提交][状态][讨论版] 题目描述 我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉我分别告诉我这个小数的循环节的循环次数.循环节以及循环节长度 输入 输入包括多组测试数据每组测试数据1行,包括一个小数,小数的长度不超过200,小数大于0小于100 输出 分别输出这个小数的循环节的长度.循环节以及循环次数,中间以

河南省第三届ACM程序设计大赛题解

光说不练是假把式,先给各大巨巨们一个刷题链接:戳我进入刷题OJ 这届比赛水题有点多,想拿奖保证好手速即可.但是想拿高名次并不太容易 A.常规做法我不太会,但是根据题目的数据发现,可以开个这么大的数组哈哈,那么万能的暴力保证1A. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=500; int num[maxn]; int main(){

Leetcode 184周赛题解

前一宿没睡好,困的不行,写的有点慢.. 5380. 数组中的字符串匹配 题目描述: 给你一个字符串数组 words ,数组中的每个字符串都可以看作是一个单词.请你按 任意 顺序返回 words 中是其他单词的子字符串的所有单词.如果你可以删除 words[j] 最左侧和/或最右侧的若干字符得到 word[i] ,那么字符串 words[i] 就是 words[j] 的一个子字符串. 题解: 两次遍历,用kmp判断一下是否是字串. AC代码: class Solution { public: in

第十周周赛题解

A题: 二分题目,具体二分公式看我代码吧(ーー゛) 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define maxa 20100 6 using namespace std; 7 int a[maxa],l[maxa],r[maxa],n; 8 bool comp(int p) 9 { 10 int x= a[1],y= p-a[1