https://ac.nowcoder.com/acm/contest/1083#question
A、 abc
题意:
给出一个字符串s,你需要做的是统计s中子串”abc”的个数。子串的定义就是存在任意下标a<b<c,那么”s[a]s[b]s[c]”就构成s的一个子串。如”abc”的子串有”a”、”b”、”c”、”ab”、”ac”、”bc”、”abc”。
输入描述:
一个字符串s。保证输入只包含小写拉丁字符。
1<=|s|<=1e5
输出描述:
一个整数表示s中子串”abc”的个数。
示例1
输入
abcabc
输出
4
思路:递推思想,水题
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
using namespace std;
ll a,ab,abc,n;
string s;
int main()
{
cin>>s;
n=s.size();
for(int i=0;i<n;i++)
{
if(s[i]=='a') a++;
else if(s[i]=='b') ab+=a;
else if(s[i]=='c') abc+=ab;
}
cout<<abc<<endl;
}
B、字串查询
题目描述
给出一个长度为n的字符串s和q个查询。对于每一个查询,会输入一个字符串t,你需要判断这个字符串t是不是s的子串。子串的定义就是存在任意下标a<b<c<d<e,那么”s[a]s[b]s[c]s[d]s[e]”就构成s的一个子串。如”abc”的子串有”a”、”b”、”c”、”ab”、”ac”、”bc”、”abc”。
输入描述:
第一行两个数n,q。1<=n,q<=1e5。 第二行一个长度为n的字符串s,所有字符都为小写拉丁字符。 接下来q行每行一个字符串t。1<=|t|<=50。
输出描述:
对于每个查询,如果t是s的字串,输出”YES”,否则输出”NO”。每个答案占一行。
示例1
输入
8 4 ababcbaa abac accb aaaa abcba
输出
YES NO YES YES
思路:因为太长,无法直接匹配,因为只有26个小写字母,可以记录其位置,然后依次查询符合条件的尽可能的左边的位置。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define maxn 100010
using namespace std;
int q,n,k;
char s[maxn],t[55];
vector<int>v[30];
void init()
{
for(int i=0;i<n;i++)
{
v[s[i]-'a'].push_back(i);
}
return;
}
int fin(int fa,int rt)
{
int l=0,r=v[rt].size(),mid=-1;
while((l+r)/2!=mid)
{
mid=(l+r)/2;
if(v[rt][mid]>fa) r=mid;
else l=mid;
}
if(r>=v[rt].size()) return -2;
return v[rt][r]>fa?v[rt][r]:-2;
}
int main()
{
scanf("%d%d",&n,&q);
scanf("%s",s);
init();
while(q--)
{
scanf("%s",t);
k=strlen(t);
int l=-1;
for(int i=0;i<k;i++)
{
l=fin(l,t[i]-'a');
if(l==-2) {break;}
}
if(l==-2) printf("NO\n");
else printf("YES\n");
}
}
C题是个结论题,身为数学系的我不会。。。
D、羊吃草
题目描述
有一个草原可以用一个1~400的数轴表示。有n头羊和q个查询。每头羊的编号分别是1,2,3…n。第i头羊只喜爱数轴上[ai,bi]这样的一个闭区间,每一时刻每头羊只可能在自己喜爱的区间的某个点上吃草。现在给出q个查询,每个查询两个整数l,r。你需要计算出在同一时刻,最多能有多少头羊同时在这个区间内吃草。数轴上每一个整点同一时刻只能容纳一只羊,羊只会在整点吃草。
输入描述:
第一行三个数n q。 第二行n个数a1 a2…an。 第三行n个数b1 b2…bn。 接下来q行每行两个数l,r。表示询问的区间。
输出描述:
对于每个查询,输出一个整数表示答案。
示例1
输入
5 3 1 1 1 2 4 1 1 1 3 5 1 5 2 5 1 3
输出
3 2 2
备注:
1<=n,q<=400 1<=ai<=bi<=400 1=l<=r<=400
思路:先讲样的区间按左端点排序,对于当前询问区间,依次从左到右每个位置安排羊吃草,左端点<=当前位置的,将其右端点加入multiset,multiset内的羊一定是可以在当前点吃草的,安排的最优是右端点小的那只,贪心思想吧。(开完班会回来有继续写的,中间断思路 了,所以写的很乱,但是1A,哈哈,胆大,过样例就交,但是讲真写的有些乱!)
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3fLL
#define maxn 500
using namespace std;
struct AA
{
int l,r,rt;
bool operator <(const AA&aa) const
{
return l<aa.l;
}
}pos[maxn];
int n,q,l,r;
bool cmp(AA aa,AA bb)
{
return aa.rt<bb.rt;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&pos[i].l);
pos[i].rt=i;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&pos[i].r);
}
sort(pos+1,pos+n+1);
while(q--)
{
scanf("%d%d",&l,&r);
multiset<int>s;
multiset<int>::iterator it;
int a=l,ans=0,c;
for(int i=1;i<=n&&a<=r;)
{
while(pos[i].l<=a&&i<=n) {s.insert(pos[i].r);i++;}
while(!s.empty())
{
it=s.begin();
c=(*it);
//cout<<c<<endl;
if(c<a) s.erase(s.begin());
else break;
}
if(!s.empty())
{
ans+=1;
a++;
s.erase(s.begin());
// cout<<i<<" ! "<<ans<<" "<<s.size()<<endl;
//system("pause");
}
else
{
a=pos[i].l;
}
while(!s.empty())
{
it=s.begin();
c=(*it);
//cout<<c<<endl;
if(c<a) s.erase(s.begin());
else break;
}
}
while(!s.empty()&&a<=r)
{
it=s.begin();
c=(*it);
if(c>=a) {s.erase(s.begin());ans++;a++;}
while(!s.empty())
{
it=s.begin();
c=(*it);
//cout<<c<<endl;
if(c<a) s.erase(s.begin());
else break;
}
}
printf("%d\n",ans);
}
}