题意:一串仅包含大写字母的字符串,求[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; }