题意:一串仅包含大写字母的字符串,求[L,R]中字典序最小的字母的个数

利用动态规划求解

#include <iostream>
#include <cstdio>
#include <cstring>

/* 
1. 利用前缀和动态规划,也可使用线段树求解,不过查询的复杂度较高 
*/
using namespace std;
int dp[100050][30]; 
char str[100050];
int T,N,Q;
int main() {
    scanf("%d",&T);
    int t = 1;
    int l,r;
    while (t <= T) {
        printf("Case #%d:\n",t++);
        scanf("%d%d",&N,&Q);
        scanf("%s",str + 1);
        memset(dp,0,sizeof(dp));
        for (int i = 1;i <= N;i++) {
            for (int j = 0;j < 26;j++) {
                dp[i][j] = dp[i - 1][j]; 
            }
            dp[i][str[i] - 'A']++;
        }
        int ans = 0;
        for (int i = 0;i < Q;i++) {
            scanf("%d%d",&l,&r);
            ans = 0;
            for (int j = 0;j < 26;j++) {
                if (dp[r][j] - dp[l-1][j] > 0) {
                    ans = dp[r][j] - dp[l-1][j];
                    break;
                }
            }
            printf("%d\n",ans);
        }
        
    } 
    return 0;
} 

线段树解法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 100500;
const int INF = 10000;

struct Node {
    int l,r;
    int minv;
    int minNum;
};
Node nodes[maxn * 4];
char str[maxn];

void build(int o,int L,int R) {
    //初始化放到build中 
    nodes[o].minv = INF;
    nodes[o].minNum = 0;
    if (L == R) {
        nodes[o].l = L;
        nodes[o].r = R;
        nodes[o].minv = str[L - 1] - 'A';
        nodes[o].minNum = 1;
        return;
    }
    int M = L + (R - L) / 2;
    build(o * 2,L,M);
    build(o * 2 + 1,M+1,R);
    int lc = o * 2,rc = o * 2 + 1;
    nodes[o].l = L;nodes[o].r = R;
    //合并 
    if (nodes[lc].minv < nodes[rc].minv) {
        nodes[o].minv = nodes[lc].minv;
        nodes[o].minNum = nodes[lc].minNum;
    }else if (nodes[lc].minv > nodes[rc].minv) {
        nodes[o].minv = nodes[rc].minv;
        nodes[o].minNum = nodes[rc].minNum;
    }else {
        nodes[o].minv = nodes[lc].minv;
        nodes[o].minNum = nodes[lc].minNum + nodes[rc].minNum;
    }
    
}
Node query(int o,int L,int R) {
    if (L == nodes[o].l && R == nodes[o].r) {
        return nodes[o];
    }
    int mid = (nodes[o].l + nodes[o].r) / 2;
    if (R <= mid) {
        return query(o * 2,L,R);
    }else if (L > mid) {
        return query(o * 2 + 1,L,R);
    }else {
        Node left = query(o * 2,L,mid);
        Node right = query(o * 2 + 1,mid + 1,R);
        Node res;
        if (left.minv < right.minv) {
            res.minv = left.minv;
            res.minNum = left.minNum;
        }else if (left.minv > right.minv) {
            res.minv = right.minv;
            res.minNum = right.minNum;
        }else {
            res.minv = right.minv;
            res.minNum = left.minNum + right.minNum;
        }
        return res;
    }
}
int main() {
    int T,N,Q;
    int u,v;
    scanf("%d",&T);
    int t = 1;
    while (T--) {
        scanf("%d%d",&N,&Q);
        scanf("%s",str);
        build(1,1,N);
        printf("Case #%d:\n",t++);
        for (int i = 0;i < Q;i++) {
            scanf("%d%d",&u,&v);
            Node res = query(1,u,v);
            printf("%d\n",res.minNum);
        }
    }
    return 0;
} 

 

posted on 2018-08-27 21:22  akira123  阅读(107)  评论(0编辑  收藏  举报