hdu 3183 st表

// 题意:从长度为 N 的字符串中删除 M 个字符,使得生成的新串的字典序最小

// 思路:反向构造

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 const int MAXN = 100010;
 4 int n;
 5 char ans[MAXN];
 6 int Min[MAXN][20], Max[MAXN][20];
 7
 8 // 建st表, ans[MAXN], n读入之后调用
 9 void makeRmq()
10 {
11     int i, j, len;
12     for(i = 1; i <= n; ++i) {
13         Min[i][0] = Max[i][0] = i;
14     }
15
16     int p, q;
17     for(j = 1; (len = 1 << j) <= n; ++j) {
18         for(i = 1; i + len - 1 <= n; ++i) {
19             p = Min[i][j - 1];
20             q = Min[i + (len >> 1)][j - 1];
21             if(ans[p] < ans[q] || (ans[p] == ans[q] && p < q)) {
22                 Min[i][j] = p;
23             }
24             else {
25                 Min[i][j] = q;
26             }
27
28 //            p = Max[i][j - 1];
29 //            q = Max[i + (len >> 1)][j - 1];
30 //            if(ans[p] > ans[q] || (ans[p] == ans[q] && p < q)) {
31 //                Max[i][j] = p;
32 //            }
33 //            else {
34 //                Max[i][j] = q;
35 //            }
36         }
37     }
38 }
39
40 // 取 [l, r] 的最小值和最大值放入 minValue 和 maxValue 中,且不需要初始化 minValue 和 maxValue
41 void ask(int l, int r, int &min_pos)
42 {
43     int pow_num, len, p, q;
44     pow_num = int(log(r - l + 1) / log(2));
45     len = 1 << pow_num;
46
47     p = Min[l][pow_num];
48     q = Min[r - len + 1][pow_num];
49     if(ans[p] < ans[q] || (ans[p] == ans[q] && p < q)) {
50         min_pos = p;
51     }
52     else {
53         min_pos = q;
54     }
55
56 //    p = Max[l][pow_num];
57 //    q = Max[r - len + 1][pow_num];
58 //    if(ans[p] > ans[q] || (ans[p] == ans[q] && p < q)) {
59 //        maxValue = ans[p];
60 //    }
61 //    else {
62 //        maxValue = ans[q];
63 //    }
64 }
65 char res[1010];
66 int tot;
67 int m;
68
69 int main()
70 {
71     while (scanf("%s%d", ans + 1, &m) != EOF) {
72         tot = 0;
73         n = strlen(ans + 1);
74         makeRmq();
75         int cnt = n - m;
76         int min_pos;
77         int l = 1, r = m + 1;
78         while (cnt--) {
79             ask(l, r, min_pos);
80             res[tot++] = ans[min_pos];
81             l = min_pos + 1;
82             ++r;
83         }
84         res[tot] = ‘\0‘;
85         int index = 0;
86         while(index <= tot - 1 && res[index] == ‘0‘) {
87             ++index;
88         }
89         if(index == tot) {
90             printf("0\n");
91             continue;
92         }
93         printf("%s\n", res + index);
94     }
95 }
时间: 2024-09-30 06:45:06

hdu 3183 st表的相关文章

Hdu 5289-Assignment 贪心,ST表

题目: http://acm.hdu.edu.cn/showproblem.php?pid=5289 Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3175    Accepted Submission(s): 1457 Problem Description Tom owns a company and he i

HDU 4123 Bob&#39;s Race:单调队列 + st表

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123 题意: 给你一棵树,n个节点,每条边有长度. 然后有m个询问,每个询问给定一个q值. 设dis[i]为:从节点i出发,不重复经过节点,所能够走的最远距离. 每次询问问你:区间[l,r]最长能有多长,同时保证 max{dis[i]} - min{dis[i]} <= q (i∈[l,r]) 题解: 首先有一个结论: 从树上的任意一个节点出发,尽可能往远走,最终一定会到达树的直径的两个端点之一.

HDU 5409 CRB and Graph 双连通缩点 + st表

HDU 5409 显然要先双连通缩成一棵树. 然后对于树上的边才有答案. 对于一条边来说, 两侧的最大值分为mx1 , mx2 , 那么 u 一定是min(mx1, mx2), v 一定是 u + 1. 这个经过仔细分析一下就能得到, 然后按dfs序建个st表就好啦. #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi firs

HDU 2586 How far away ? &lt;&lt; LCA转RMQ+ST表 求树上任两点最短距离裸题

此题还有LCA+tarjin离线查询做法,详见这里 关于ST表 解决RMQ问题,dp[i][j]表示从第i位开始长度为(1<<j)的区间的最值 维护的时候采用倍增思想,维护dp[i][j+1]=opt(dp[i][j],dp[i+(1<<j)][j]) 查询的时候,两端点为l,r,则长度len=r-l,寻找一个k,使(1<<k)大于等于len/2,这样就使得 [l,l+(1<<k)]和[r-(1<<k),r]覆盖整个区间 然后此时,就可以直接用s

hdu 6704 K-th occurrence 二分 ST表 后缀数组 主席树

我们考虑,一个子串必定是某个后缀的前缀. 排序相邻的后缀他们的前缀一定最相似. 所以全部的一种子串必定是一些排序相邻的后缀的公共前缀. 从l开始的子串,则从rank[l]开始看,两侧height保证大于子串长度,能延伸多长,则证明有多少个这种子串. 我们用ST表维护出height的最小值,然后通过最小值二分即可,边界有些棘手. 然后我们就得到了一个height不小于子串长度的连续区间,这个区间是以原后缀的字典序排序的. 而同时,sa数组下标为排序,值为原串位置. 所以我们对这个区间在sa数组上做

HDU 2586(LCA欧拉序和st表)

什么是欧拉序,可以去这个大佬的博客(https://www.cnblogs.com/stxy-ferryman/p/7741970.html)巨详细 因为欧拉序中的两点之间,就是两点遍历的过程,所以只要找遍历过程中对应的最小的深度就行了,这里用st表存,first存第一个u出现的地方,用value存欧拉序,同时用depth存对应深度 模板 1 struct node{ 2 int v,next,dist; 3 }a[maxn<<1]; 4 int n,m,tot,len; 5 int st[m

hdu 3183 A Magic Lamp(RMQ)

A Magic Lamp                                                                               Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Kiki likes traveling. One day she finds a magic lamp, u

RMQ问题 - ST表的简单应用

2017-08-26 22:25:57 writer:pprp 题意很简单,给你一串数字,问你给定区间中最大值减去给定区间中的最小值是多少? 用ST表即可实现 一开始无脑套模板,找了最大值,找了最小值,分别用两个函数实现,实际上十分冗余 所以TLE了 之后改成一个函数中同时处理最大值和最小值,就可以了 AC代码如下: /* @theme:poj 3264 @writer:pprp @declare:ST表(sparse table)稀疏表,用动态规划的思想来解决RMQ问题: @date:2017

[模板]ST表浅析

ST表,稀疏表,用于求解经典的RMQ问题.即区间最值问题. Problem: 给定n个数和q个询问,对于给定的每个询问有l,r,求区间[l,r]的最大值.. Solution: 主要思想是倍增和区间dp. 状态:dp[i][j] 为闭区间[i,i+2^j-1]的最值. 这个状态与转移方程的关系很大,即闭区间的范围涉及到了转移方程的简便性. 转移方程:dp[i][j]=max(dp[i][j-1],dp[i+2^(j-1)][j-1]). 这是显然的,但这里有个细节:第一个项的范围为[i,i+2^