感觉自己在家里面待了几天...脑子好像费了(其实也没有吧)就是没有那么活跃了,那么就开始康复训练了!!
周一到周三vp了3场,感觉自己好菜....不会啊....然后发现补题也补的好艰难啊!!!
/(ㄒoㄒ)/~~
div3的A题,md想了快20多分钟才出来,真的菜..
当时读题也读的异常艰难...
自己也写的异常麻烦啊..直接写了4个循环...真服了我自己了...
赛后直接问lb,然后他的做法挺简单的,首先打表列出需要的字符,然后在遍历列和行即可
如果找到了就break跳出这列
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int n,m;
char a[25][25];
vector<int>s[10];
int main(){
scanf("%d",&t);
while(t--){
for(int i=1;i<=4;i++)s[i].clear();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]=='v')s[1].push_back(j);
if(a[i][j]=='i')s[2].push_back(j);
if(a[i][j]=='k')s[3].push_back(j);
if(a[i][j]=='a')s[4].push_back(j);
}
}
sort(s[1].begin(),s[1].end());
sort(s[2].begin(),s[2].end());
sort(s[3].begin(),s[3].end());
sort(s[4].begin(),s[4].end());
if(s[1].size()==0){
printf("NO\n");
continue;
}
int pos=s[1][0];
int now;
now=pos;
for(auto x:s[2]){
if(x>pos){
pos=x;
break;
}
}
if(pos==now){
printf("NO\n");
continue;
}
now=pos;
for(auto x:s[3]){
if(x>pos){
pos=x;
break;
}
}
if(pos==now){
printf("NO\n");
continue;
}
now=pos;
for(auto x:s[4]){
if(x>pos){
pos=x;
break;
}
}
if(pos==now){
printf("NO\n");
continue;
}
printf("YES\n");
}
return 0;
}
B题直接秒了,简单的很...
这个C题还是很有意思的:
判读旋转过后是否是对称..,一开始我想直接图像是否对称但是不好判读,我还百度了一下,对称有选择对称和中心对称...
然后我就想别的方法了,然后就有思路了
我们用mp[i]存旋转前高度为i的木块的数量,可以发现旋转后高度的范围为1到n,还有宽度为1且高度为i的木块的数目为a[i]-a[i+1],如果等于mp[i]的话是满足条件的否则就是不满足条件的!
还有注意n为1且a[1]为1是满足条件的,其他是不满足条件的
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int n;
int a[200005];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
map<ll,ll>mp;
for(int i=1;i<=n+5;i++)a[i]=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mp[a[i]]++;
}
int flag=1;
if(n==1&&a[1]!=1){
printf("NO\n");
continue;
}
for(int i=1;i<=n;i++){
if(a[i]-a[i+1]==mp[i]){
continue;
}else{
flag=0;
break;
}
}
if(flag==0){
printf("NO\n");
}else{
printf("YES\n");
}
}
return 0;
}
D:md这题我连样例怎么来的都不知道,做不出来..赛后看了题解也没有看懂!!!
这题也花了20多分钟,真的服了自己了,还是太菜了,赛后想了想,当时我只是感觉我觉得对,就写了,连样例都没试...
一开始我只想检验样例是否合法...最后发现是错误的..
以后还得改变一下做题方法,一定要先想明白在写,如果想明白了,代码还是很好写的
1.如果是()的话无解,这点其实很好想,否则的话都有解
2.如果样例的括号是交错的,一个(,然后一个),比如这样,我们构造(((())))
如果不是交错的,我们构造()()()()
纯纯数学题,但是没出来....好伤心...
感觉还是自己畏惧了,之前自己做过这样的题,然后自己都没做出来....然后再做的时候可能就有一点畏惧了吧,也担忧自己出不来..(都是借口..)
当时思路很混乱啊....不知道怎么才是最优的..但肯定的是这题一定是贪心..
但是最后也没有贪出来...
1.要使额外需要的钱的数目最少,能肯定的是,一定要多拿价值为k的,少拿价值为1的
2.根据1,我们需要m/k张价值为k的,m%k张价值为1的
3.如果1有剩余的,我们可以用k张1来少拿一张k
3.我们额外需要拿k的张数takek= max(0,m/k-ak),额外需要拿1的张数take1=max(0,m%k-a1)
1剩余的张数 left1=max(0,a1-m%k),剩余的1能转换的k的数目 x=left1/k;
4.答案为 take1+takek-min(takek,x);
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int main(){
scanf("%d",&t);
while(t--){
int m,k,a1,ak;
cin>>m>>k>>a1>>ak;
int needk=m/k;
int need1=m%k;
int take1=max(0,need1-a1);
int left1=max(0,a1-need1);
int takek=max(0,needk-ak);
int res=min(takek,left1/k);
printf("%d\n",take1+takek-res);
}
return 0;
}
这题又没出来.../(ㄒoㄒ)/~~...
是一道博弈论的题目,但是我想的还是太简单了3...
我想的是如果1到i的话如果只有一个满足条件的话,那么Alice一定赢,但是还是我想的太简单了...
Bob赢的方式有i前面有必定赢局面或者前面没有路可以走了,‘
Alice赢的方式就是BoB输的情况了。
然后就是博弈论递推了..
我们设minn为前i的最小的值,minwin为必赢局面的最小值,
如果 x<a[i]&&x>minwin(有路并且没有必赢局面)的话,那么就一定Alice赢
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t,n;
int a[300005];
int main(){
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int minn=n+1;
int minwin=n+1;
int ans=0;
for(int i=1;i<=n;i++){
if(minn<a[i]&&a[i]<minwin){
ans++;
minwin=min(minwin,a[i]);
}
minn=min(minn,a[i]);
}
printf("%d\n",ans);
}
return 0;
}
然后就是练习赛了..我只能说这是我遇到最恶心的练习赛了...
恶心死了...
b题就有一点难度,但是我出了.花了18分钟吧..还是挺慢的了.
感觉还是高中的概率吧..不是很难,然后就是控制精度
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
double a1,b1,c1;
double a2,b2,c2;
cin>>a1>>b1>>c1;
cin>>a2>>b2>>c2;
if(a1==a2&&a1==10){
printf("Sorry,NoBruteForce\n");
continue;
}
if(b1==b2&&b1==10){
printf("Sorry,NoBruteForce\n");
continue;
}
if(c1==c2&&c1==10){
printf("Sorry,NoBruteForce\n");
continue;
}
a1=a1*0.1;
a2=a2*0.1;
b1=b1*0.1;
b2=b2*0.1;
c1=c1*0.1;
c2=c2*0.1;
double ans=0;
double ping=a1*a2+b1*b2+c1*c2;
double win=1-ping;
double cnt=1;
double x=1;
while(1){
double now;
if(cnt==1){
now=cnt*x*win;
}else{
x=x*ping;
now=cnt*x*win;
}
cnt++;
ans=ans+now;
if(now<1e-5)break;
}
cout<<ans<<endl;
}
return 0;
}
先不说C题,感觉c题是真的恶心啊....
d题题目很好理解..但就是没啥思路..........
还是菜啊...
正解:
从后往前和从前往后是一样的
我们用mp存每个牌的个数
然后遍历1到n,如果mp[i]不为0,我们就在枚举i到n同时维护cnt(cnt为连续的牌数)如果mp[j]>mp[j+1]就break
如果cnt>=5就继续只到mp[i]为0,否则输出No
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int n;
int a[200005];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
map<int ,int>mp;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
mp[a[i]]++;
}
int flag=0;
for(int i=1;i<=n;i++){
if(flag){
break;
}
while(mp[i]){
int cnt=0;
for(int j=i;j<=n;j++){
if(mp[j]==0)break;
mp[j]--;
cnt++;
if(mp[j]+1>mp[j+1])break;
}
if(cnt<5){
printf("NO\n");
flag=1;
}
cnt=0;
if(flag){
break;
}
}
}
if(flag){
continue;
}
printf("yes\n");
}
return 0;
}
这题我感觉是真的恶心....
都有点不想写题解了...
有两种做法:dp和贪心
dp:我们设dp[i]为形成1到i的排列所需的最少子段数目,
g[i]为i从i-1到0没有与i在一个子段的最小的数
注意j是全局变量!!!.md就是因为这个j写在for循环里面一直有个点不懂
for(int i=1;i<=m;i++){
dp[i]=min(dp[i],dp[g[i]]+1);
}
int j=1;
for(int i=1;i<=n;i++){
if(i!=1&&a[i]!=a[i-1]+1)j=i;
if(a[i]<=m)g[a[i]]=min(g[a[i]],a[j]-1);
}
最后的dp[m]就为答案,如果dp[m]>m的话,说明无解
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int a[200005];
int main(){
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
vector<int>dp(m+5,m+1),g(m+5,m+1);
dp[0]=0;
int j=1;
for(int i=1;i<=n;i++){
if(i!=1&&a[i]!=a[i-1]+1)j=i;
if(a[i]<=m)g[a[i]]=min(g[a[i]],a[j]-1);
}
for(int i=1;i<=m;i++){
dp[i]=min(dp[i],dp[g[i]]+1);
}
if(dp[m]<=m){
printf("%d\n",dp[m]);
}else{
printf("-1\n");
}
}
return 0;
}
贪心:
牛客练习赛 114_Unlimitedz的博客-CSDN博客
在网上找的一个方法,感觉这方法有点极限啊....
700多ms过的...如果数据再极限点的话肯定就过不了了..但是他真种做法的思想还是很好的..
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
#include<unordered_set>
#include<unordered_map>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
struct Node{
int x,y;
}b[200005];
int a[200005];
bool cmp(Node s1,Node s2){
return s1.x<s2.x;
}
int main(){
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int cnt=0;
for(int i=1;i<=n;i++){
if(i+1<=n&&a[i+1]==a[i]+1){
int j=i;
while(j+1<=n&&a[j+1]==a[j]+1){
j++;
}
b[++cnt].x=a[i];
b[cnt].y=a[j];
i=j;
}else{
b[++cnt].x=a[i];
b[cnt].y=a[i];
}
}
sort(b+1,b+1+cnt,cmp);
int ans=0;
int flag=0;
int l=1;
int r=0;
for(int i=1;i<=cnt;i++){
if(b[i].x>l){
flag=1;
break;
}
ans++;
int j=i;
while(j<=cnt&&b[j].x<=l){
r=max(r,b[j].y);
j++;
}
if(r>=m)break;
l=r+1;
}
if(r<m||flag){
printf("-1\n");
}else{
printf("%d\n",ans);
}
}
return 0;
}