2018"百度之星"程序设计大赛 - 资格赛 - 子串查询

题目链接:点击打开链接

题目大意:给定一个区间,求在这个区间中最小的字符char个数是多少。

解题思路:差分前缀和版 + 树状数组版。

AC 代码(差分前缀和)

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

int a[100005][26];
char s[100005];

int main()
{
    int T; scanf("%d",&T);
    int n,q,l,r,kase=1;
    while(T-- && ~scanf("%d%d",&n,&q))
    {
        mem(a,0);
        scanf("%s",s);
        int len=strlen(s);
        a[0][s[0]-'A']++;
        for(int i=1;i<len;i++)
        {
            a[i][s[i]-'A']++;
            for(int j=0;j<26;j++)
                a[i][j]+=a[i-1][j];
        }

        printf("Case #%d:\n",kase++);
        while(q--)
        {
            scanf("%d%d",&l,&r);
            int rs=0;
            for(int i=0;i<26;i++)
            {
                if(a[r-1][i]>a[l-1-1][i])
                {
                    rs=a[r-1][i]-a[l-1-1][i]; break;
                }
            }
            printf("%d\n",rs);

        }
    }

    return 0;
}

AC 代码(树状数组)

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

const int maxn=1e5+10;

int n,q,T,kase=1;
int rs1[maxn];     // 记录最小值
int rs2[maxn][26]; // 前缀和
char s[maxn];

int lowbit(int x)
{
    return x & -x;
}

void update_min_cnt(int x,int val)
{
    while(x<=n)
    {
        rs1[x]=min(rs1[x],val);
        rs2[x][val]++;
        x+=lowbit(x);
    }
}

int query_min(int l,int r)
{
    int ans=s[r]-'A';
    while(l!=r)
    {
        for(r--;r-lowbit(r)>=l;r-=lowbit(r))
            ans=min(ans,rs1[r]);
        ans=min(ans,s[r]-'A');
    }

    return ans;
}

int query_cnt(int l,int r)
{
    int val=query_min(l,r);
    int ans1=0,ans2=0;
    while(r>0)
    {
        ans1+=rs2[r][val];
        r-=lowbit(r);
    }

    r=l-1;
    while(r>0)
    {
        ans2+=rs2[r][val];
        r-=lowbit(r);
    }

    return ans1-ans2;
}

int main()
{
    scanf("%d",&T);
    while(T-- && ~scanf("%d%d",&n,&q))
    {
        printf("Case #%d:\n",kase++);
        scanf("%s",s+1);
        int len=strlen(s+1);
        mem(rs1,INF); mem(rs2,0);
        for(int i=1;i<=len;i++)
            update_min_cnt(i,s[i]-'A');

        int l,r;
        while(q--)
        {
            scanf("%d%d",&l,&r);
//            printf("%c\n",char(query_min(l,r)+'A'));
            printf("%d\n",query_cnt(l,r));
        }
    }

    return 0;
}

/*
10
9 3
ABEBBDCFC
3 7
1 1
1 6
*/

猜你喜欢

转载自blog.csdn.net/Dream_Weave/article/details/81414704