文章目录
A - Shell Game (思维)
Descriprition
给 0,1,2, 3个盒子 ,盒子按照 奇数次移动时,0与1 交换位置, 偶数次移动时1与 2 交换位置, 告诉小球n 次移动后 最后在 盒子中的位置, 求小球初始时放入位置
Solution
显然 移动 是有周期的,周期为6
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[7][3]={{0,1,2},{1,0,2},{1,2,0},{2,1,0},{2,0,1},{0,2,1},{0,1,2}};
int main()
{
long long n,x;
long long a1,a2,a3;
scanf("%lld %lld",&n,&x);
n=n%6;
printf("%d\n",a[n][x]);
return 0;
}
B - Game of Credit Cards (贪心)
Descriprition
a与b 玩游戏,每个人 给 n 个数,每回合两个人各出一个数,数 小的人 输一局
问b 最少能 输几局, 最多 能赢几局
Solution
将数 从小到大 排序,比较
最少输的局数,尽可能平局或胜利
最多赢的局数 ,尽可能胜利
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int n;
int a[N],b[N];
char s1[N],s2[N];
int main()
{
cin>>n>>s1>>s2;
for(int i=0;i<n;i++)
{
a[i]=s1[i]-'0';
b[i]=s2[i]-'0';
}
sort(a,a+n);
sort(b,b+n);
int cnt1=0,cnt2=0; // 牌的指针
int ans1=0,ans2=0;
while(cnt1<n&&cnt2<n)
{
if(a[cnt1]<=b[cnt2])
{
cnt1++;
cnt2++;
}
else cnt2++;
}
ans1=n-cnt1;
cnt1=0,cnt2=0;
while(cnt1<n&&cnt2<n)
{
if(a[cnt1]<b[cnt2])
{
ans2++;
cnt1++;
cnt2++;
}
else cnt2++;
}
printf("%d\n%d\n",ans1,ans2);
return 0;
}
C - Alyona and Spreadsheet (dp)
Descriprition
给n行m列的矩阵,每次 查询 (l,r) 从 l 行到 r 行, 是否存在某一 j 列 保持 连续的 不下 降序列,即 ai, j ≤ ai + 1, j for all i from l to r - 1
Solution
使用vector 原因 是 n*m<=1e5 , 要动态开辟数组
dp 思路, dp[i][j] 存放 该元素 向下的 最长 连续的 不下 降序列的长度
dp(i, j) = up(i + 1, j) + 1, ai, j < =ai + 1, j;
dp(i, j) = 1 otherwise.
num[i] 第i 行的 存在的最大 连续不下降序列的 长度;
num[i] =max(num[i] ,dp[i] [j]) (1=<j<=m)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
vector< vector<int> >a;
vector< vector<int> >b;
//int num[N];
vector<int >num;
int n,m;
// b[i][j] 存放第i行第j列的 元素 在第j列向下 最长的连续不下降序列的 长度
// num[i] 第i 行的 存在的最大 连续不下降序列的 长度;
void dp()
{
b.resize(n,vector<int >(m,0));
num.resize(n,0);
for(int i=0; i<m; i++)
b[n-1][i]=1;
num[n-1]=1;
for(int i=n-2; i>=0; i--)
{
for(int j=0; j<m; j++)
{
if(a[i][j]<=a[i+1][j])
{
b[i][j]=b[i+1][j]+1;
}
else
b[i][j]=1;
num[i]=max(num[i],b[i][j]);
}
}
}
int main()
{
int x,k;
scanf("%d %d",&n,&m);
// a.resize(n,vector<int>(m,0));
for(int i=0; i<n; i++)
{
a.push_back( vector<int>() );
for(int j=1; j<=m; j++)
{
scanf("%d",&x);
a[i].push_back(x);
}
}
/* for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
printf("%d ",a[i][j]);
printf("\n");
}*/
dp();
scanf("%d",&k);
int l,r;
for(int i=1; i<=k; i++)
{
scanf("%d %d",&l,&r);
l--,r--;
if(num[l]>=(r-l+1))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}
D - Cloud of Hashtags (字符串排序)
Descriprition
n个字符串, 保证从上到下,保持字典序(从小到大,可以相等), 可删去串的 任意长度的 后缀
Solution
从下往上遍历 去删除 不符合字典序的 后缀
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
string s1[N];
int main()
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
cin>>s1[i];
int i,j,k;
int len1,len2,cnt;
for( j=n-1; j>=1; j--)
{
i=j-1;
if(s1[i]>s1[j])
{
len1=s1[i].size();
len2=s1[j].size();
cnt=-1;
while(++cnt<=min(len1,len2))
{
if(s1[i][cnt]>s1[j][cnt])
{
s1[i].erase(s1[i].begin()+cnt,s1[i].end());
break;
}
}
}
}
/*
* 提供另一种比较方法, 显然对于字典序的比较,
* 当i位置 出现不同字母时,两个串字典序 必定会区分出大小
* 在判断出是 字典序s[i]>s[i+1] 时,
* 当两个串 出现不同字母时,必定是 i 串 出现 字典序较大的字母
*/
/* for(int i=n-2; i>=0; i--)
{
if(s[i]>s[i+1])
{
int l=max(s[i].size(),s[i+1].size());
for(int j=0; j<l; j++)
{
if(s[i][j]!=s[i+1][j])
{
s[i][j]='\0';
break;
}
}
}
}
*/
for(int i=0; i<n; i++)
{
cout<<s1[i]<<endl;
}
return 0;
}
E - Hanoi Factory (贪心+单调栈)
Descriprition
n个 圆环,给每个圆环的内径 a,外径 b,圆环高度 h,当 两个圆环的 b1<=b2, b1>a1
则 1环 可以落在 2 上面,高度叠加,求圆环相叠的最大高度
Solution
将所有环 按外径从大到小排序,外径相等时 在将内径从大到小排序
内径从大到小排序的原因:外径逐渐减小时,内径要尽可能小 才能叠加更多的环
单调栈,维护 第i 个环 进入时的最大高度
为什么符合单调栈 ,因为 当 第 i 个位置 不符合叠加条件是,显然后面的环也不符合叠加
此时符合栈的 后入先出 条件
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n;
const int N=1e5+10;
typedef struct
{
int a,b,h;
} stu ;
stu p[N];
int cmp(stu x,stu y)
{
if(x.b!=y.b)
return x.b>y.b;
else
return x.a>y.a;
}
stack<stu>s;
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d %d %d",&p[i].a,&p[i].b,&p[i].h);
}
sort(p+1,p+1+n,cmp);
long long ans=0,sum=0;
for(int i=1; i<=n; i++)
{
while(!s.empty()&&p[i].b<=s.top().a)
{
sum-=s.top().h;
s.pop();
}
s.push(p[i]);
sum+=p[i].h;
ans=max(ans,sum);
}
printf("%lld\n",ans);
return 0;
}