第一次达成度这么高(虽然是div3的比赛),相信以后会更好!
提交传送门
A.Candies and Two Sisiters
题目大意:实实在在的水题,给你一个数n,你需要找出两个数a,b使a+b=n,但条件是1.a>b,2.a>0且b>0
输出这样子的a,b有多少对
思路:直接二半分(n-1)/2.
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
int main(void)
{
ll t,n,a,b,c=0;
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
printf("%lld\n",(n-1)/2);
}
}
B. Construct the String
题目大意:题目给你三个数:n,a,b,你的任务是:构成一个长度为n的(只有26个小写字母)字符串,该字符串的约束条件:在一连续长度为a的子串中有b个不同类型的字符。最后输出这个字符串(答案不唯一)
思路:简简单单,就先看b是多少,然后每次顺序输出(a,b…z)这样子的连续串,长度为b,记住字符串长度不能超过n。(压根与a是多少毫无关系)
这就是一个n长度的串——abcabca,可以看出每长度为5的子串都有3个不同类型的字符。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
int main()
{
ll t,n,a,b,w;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&n,&a,&b);
while(n)
{
for(int i=0;i<b&&n>0;i++)
{
printf("%c",'a'+i);
n--;
}
}
cout<<endl;
}
return 0;
}
C. Two Teams Composing
C题(二分+贪心算法+排序)?-?
题目大意:给你一个元素个数为n的数组,你的任务是将这个数组分成两个元素数量都为 x 的子数组A,B,对于A数组,其元素一定全部都是不一样的,对于B数组,其元素一定全部都是一样的,其中A中某些元素可以与B数组的某些元素是一样的,你现在目的是怎样不重复地分配才能使 x 尽可能最大并输出这个最大的 x 。(x+x<=n)
思路::(手动滑稽)我这题是写的最乱的,大家可以看看别人的博客
#include<bits/stdc++.h>
typedef long long int ll;
const int size = 2e5+50;
using namespace std;
ll flag[size],bj[size];
int main()
{
ll t,n,a[size];
scanf("%lld",&t);
while(t--)
{
memset(flag,0,sizeof(flag));
memset(bj,0,sizeof(bj));
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
flag[a[i]]++;
}
ll c1=0,c2=0,ma=1;
for(int i=1;i<=n;i++)
{
if(flag[a[i]]==1) c2++;
else if(flag[a[i]]>1 && bj[a[i]]==0)
{
c1++;
bj[a[i]]=1;
ma=max(ma,flag[a[i]]);
}
}
if(n==1) cout<<"0"<<endl;
else
{
ll mid = ma;
if(c1+c2-1>=ma);
else if(c1+c2<ma) ma=c1+c2;
else if(c1+c2>=ma-1) ma=min(ma-1,c1+c2);
printf("%lld\n",ma);
}
}
return 0;
}
D. Anti-Sudoku
D题(构造算法+模拟)
题目大意:给你一个正确的数独,你现在有最多九次改变数独里面数的机会,你的任务是将原来正确的数独经过你的改变后变成了这样子的数独——每行每列每3x3宫格至少有两个相同的数,输出你改变后的数独(答案肯定不唯一)
思路::(十分水的题目,但想了有那么久,脑子还是反应慢了。)做九次下面的变化:
很清楚看的到,我修改的九个位置都控制着独立的一行,独立的一列,独立的3x3宫格,与其他的改变点互不干扰。
#include<bits/stdc++.h>
typedef long long int ll;
const int size = 2e5+50;
using namespace std;
char sd[11][11];
int jl[11];
int main()
{
ll t,n,a[size];
scanf("%lld",&t);
getchar();
while(t--)
{
for(int i=0;i<9;i++)
gets(sd[i]);
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(i==0&&j==0) cout<<(sd[i][j]-'0')%9+1;
else if(i==1&&j==3) cout<<(sd[i][j]-'0')%9+1;
else if(i==2&&j==6) cout<<(sd[i][j]-'0')%9+1;
else if(i==3&&j==1) cout<<(sd[i][j]-'0')%9+1;
else if(i==4&&j==4) cout<<(sd[i][j]-'0')%9+1;
else if(i==5&&j==7) cout<<(sd[i][j]-'0')%9+1;
else if(i==6&&j==2) cout<<(sd[i][j]-'0')%9+1;
else if(i==7&&j==5) cout<<(sd[i][j]-'0')%9+1;
else if(i==8&&j==8) cout<<(sd[i][j]-'0')%9+1;
else cout<<sd[i][j];
}
cout<<endl;
}
}
return 0;
}
E2Three Blocks Palindrome (haed version)(前缀数组和+二分+暴力)
E1与E2的题我只讲E2,这个就考察一定的代码功底了,两个题目的意思是一样的,但是E2有点卡空间的感觉,你稍稍开大点数组说不定就会MLE,当然你拿E1的AC代码来交E2大部分情况是TLE的(吐槽一番,我就干过这个傻事)(过了E2一定可以过E1)
题目大意:给你一个元素个数为n的数组,你可以删除这个数组里面的某些数,但不能全部删除,可以不删除。你的任务是:这个数组经过你的改变后要满足以下条件——数组可以分成三块:
注意,这个数组不是回文!!!(坑死都不知道)
思路:直接从E2这里出发
1.我们开辟一个数组pos[200010][202],用来存储在第i个位置和第i个位置之前数字j出现的次数之和,记作pos[i][j]。
2.我们再用STL里面的vector开辟202个动态数组 vector ve[202]。用来 记录每个数字出现的位置
3.为什么是202,因为题目说数组内的元素最大是200,为了防止MTL,所以开辟比200大一点点就可以了。
4.接下来看图演示:(题目输出x+x+y的最大值)
我把代码贴上来说明一下:
#include<bits/stdc++.h>
using namespace std;
const int size = 2e5+11;
vector<int> ve[202];
int pos[size][202];
int main(void)
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int v=0;
for(int i=1;i<=200;i++) ve[i].clear();
for(int i=1;i<=n;i++) for(int j=1;j<=200;j++) pos[i][j]=0;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
v=max(v,x);
for(int j=1;j<=v;j++)
pos[i][j] = pos[i-1][j]+(j==x);
ve[x].push_back(i);
}
int sum=0;
for(int i=1;i<=v;i++)
{
int l=0,r=ve[i].size()-1;
sum=max(sum,r+1);//这是为了保证最小的目标串长度
//因为每个ve都可以组成一个长度为ve[i].size()的目标串
//我们下面的代码只是寻找有没有比这个更长的,有就更换。
while(l<r)
{
int mid=0;
int right = ve[i][r];
//i这个数出现在题目数组最远的位置是right
int left = ve[i][l];
//i这个数出现在题目数组最近的位置是left
for(int j=1;j<=v;j++)
mid=max(mid,pos[right-1][j]-pos[left][j]);
//这个mid是为了求最近的i和最远的i之间存在的最大的y
//y就是上面题目大意讲解的那个y,为什么肯定这个y就一定
//有y个相同的数,而且是夹在i左右之间,因为这个pos数组
//求的是j这个数在i左右位置出现的次数,那肯定都是一类
//相同的数。
sum=max(sum,mid+2*(l+1));
//这个mid+2*(l+1)就是你求出来的x+x+y的值,mid的看作y,
//l+1看作是x,这个循环能进行的次数越多,代表ve[i]这个
//size就越大。
l++,r--;
}
}
printf("%d\n",sum);
}
}
最后一题好好理解,我讲的可能模棱两可,凡事还得靠自己,加油!