其實這套題目不難,D題自己想也能想到那一塊,只是對stl用法還沒有那麼熟。。
第一題,水題
AC程式碼:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int a[102];
int main()
{
int n,d,i,p;
int ans;
while(~scanf("%d%d",&n,&d))
{
ans=0;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
scanf("%d",&p);
if(p<=n)
{
for(i=0;i<=p-1;i++)
{
ans+=a[i];
}
printf("%d\n",ans);
}
else
{
for(i=0;i<n;i++)
{
ans+=a[i];
}
p-=n;
ans-=d*p;
printf("%d\n",ans);
}
}
return 0;
}
就是這個水題,竟然當時把題目理解成最大了,還去叉別人的程式碼。。坑。。
第二題,水題
AC程式碼:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
using namespace std;
int a[100005];
map<int,int> mq;
int ans[100005];
int main()
{
int i,n,m,t;
while(cin>>n>>m)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
mq.clear();
ans[n]=1;
mq[a[n]]=1;
for(i=n-1;i>=1;i--)
{
if(mq[a[i]])
{
ans[i]=ans[i+1];
}
else
{
mq[a[i]]=1;
ans[i]=ans[i+1]+1;
}
}
for(i=1;i<=m;i++)
{
scanf("%d",&t);
printf("%d\n",ans[t]);
}
}
return 0;
}
第三題,還算是比較有意思,只是題目有點難懂而已。
有一個字串,只由xyz字元組成。給m個詢問,每個詢問限定一個子串,該字串可以任意順序排列,如果存在一個排列,其中所有三個字元大小的子串都是由"zyx",
"xzy", "yxz"中的一個字串組成的,則返回“”YES“,否則返回”NO“,如果字串不足三個,返回”YES“。
思路:其實就是統計子串中x,y,z的個數,符合要求的情況下,x,y,z個數中,最大的個數和最小的差不會超過一個。
當然我是慢慢找規律,先搞一個串xzyxzyxzy,然後兩邊不斷剝掉,統計個數即可。
AC程式碼:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
using namespace std;
char a[100005];
int dpx[100005];
int dpy[100005];
int dpz[100005];
int main()
{
int len,i,m,l,r;
while(~scanf("%s",a+1))
{
len=strlen(a+1);
dpx[0]=dpy[0]=dpz[0]=0;
for(i=1;i<=len;i++)
{
dpx[i]=dpx[i-1];
dpy[i]=dpy[i-1];
dpz[i]=dpz[i-1];
if(a[i]=='x') dpx[i]++;
if(a[i]=='y') dpy[i]++;
if(a[i]=='z') dpz[i]++;
}
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
int xx,yy,zz;
xx=dpx[r]-dpx[l-1];
yy=dpy[r]-dpy[l-1];
zz=dpz[r]-dpz[l-1];
if(xx+yy+zz<3) puts("YES"); //
else if(xx==yy&&yy==zz) puts("YES"); //0 0
else if(yy==zz&&xx==yy-1) puts("YES"); //0 1
else if(yy==xx&&zz==yy+1) puts("YES"); //0 2
else if(xx==yy&&zz==yy-1) puts("YES"); //1 0
else if(xx==zz&&yy==xx+1) puts("YES"); //1 1
else if(yy==zz&&xx==yy+1) puts("YES");
else if(xx==zz&&yy==xx-1) puts("YES");
else
puts("NO");
}
}
return 0;
}
第四題,
題意:給兩個陣列a和b,找出a中所有可能的q (q + (m - 1)·p ≤ n; q ≥ 1),
使得序列aq, aq + p, aq + 2p, ..., aq + (m - 1)p,能夠由陣列b改變值的順序排列而成。
解題思路:先根據%p分組,然後對組內進行處理,移動的時候可以使用兩個指標,
l和r不斷右移。用mq記錄b中每個數值能夠使用的次數,當存在滿足的情況時,
mq中所有的數值都正好使用完,一組之內之後的情況需要減掉序列最前面的一個值的
使用,加上序列之後新增加的值,並記錄當前狀態的滿足情況。
題目地址:B.
Sereja ans Anagrams
AC程式碼:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=2e5+5;
map<int,int> mq;
vector<int> ans;
int a[maxn],b[maxn];
int main()
{
long long n,m,p,i,j;
while(cin>>n>>m>>p)
{
ans.clear();
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<=m;i++) scanf("%d",&b[i]);
for(i=1;i<=p&&(i+(m-1)*p)<=n;i++)
{
mq.clear();
for(j=1;j<=m;j++) mq[b[j]]++; //先把b的元素種類和個數都儲存起來
int step=0;
for(j=i;;j+=p)
{
if(step==m) break;
mq[a[j]]--;
if(mq[a[j]]==0) mq.erase(a[j]);
step++;
}
int l,r; //用兩個指標對一個組的進行遍歷
l=i,r=l+m*p;
if(mq.size()==0) ans.push_back(l);
while(1)
{
if(r>n) break;
mq[a[l]]++,mq[a[r]]--;
if(mq[a[r]]==0) mq.erase(a[r]);
if(mq[a[l]]==0) mq.erase(a[l]);
l+=p,r+=p;
if(mq.size()==0) ans.push_back(l);
}
}
sort(ans.begin(),ans.end());
printf("%d\n",ans.size());
for(i=0;i<ans.size();i++)
{
if(i) printf(" ");
printf("%d", ans[i]);
}
cout<<endl;
}
return 0;
}