其实这套题目不难,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中所有的数值都正好使用完,一组之内之后的情况需要减掉序列最前面的一个值的使用,加上序列之后新增加的值,并记录当前状态的满足情况。
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; }
作者:opm777 发表于2013-11-29 1:18:51 原文链接
阅读:98 评论:0 查看评论