2016-5-15 交流会2 (百度之星资格赛,树形dp , 单调队列/栈,ST算法)

/* 如果已经在自己的博客上写了,格式:

    hdu4122  Alice's mooncake shop[你博客的链接]  (题目类型 )

  如果向直接发表在这里,格式:

  hdu4122  Alice's mooncake shop (题目类型)

 题意。。。。+数据范围

 解题思路:。。。。

 防或不防自己的代码。。。

 ----------------------------------------------------------------

 叙述尽量精简,题好不在题多。

-----------------------------------------------------------------------------------------------------------------

能结合题目讲就尽量吧,,,,==没了

//仓鼠区,禁止投喂{

2016"百度之星" - 资格赛(Astar Round1)

Problem A

Problem Description

度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串。现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值。一个字符串的哈希值,由以下公式计算得到:

H(s)=i=1ilen(s)​​(Si​​28) (mod 9973)

Si​​代表 S[i] 字符的 ASCII 码。

请帮助度熊计算大字符串中任意一段的哈希值是多少。

Input

多组测试数据,每组测试数据第一行是一个正整数NN,代表询问的次数,第二行一个字符串,代表题目中的大字符串,接下来NN行,每行包含两个正整数aa和bb,代表询问的起始位置以及终止位置。

1N1,000

1len(string)100,000

1a,blen(string)

Output

对于每一个询问,输出一个整数值,代表大字符串从 aa 位到 bb 位的子串的哈希值。

Sample Input
2
ACMlove2015
1 11
8 10
1
testMessage
1 1
Sample Output
6891
9240
88


 1 #include <cmath>
 2 #include <cstdio> 
 3 #include <cstdlib> 
 4 #include <cstdio> 
 5 #include <cstdlib> 
 6 #include <cstring> 
 7 using namespace std; 
 8 #define REP(i, a, b) for (int i = (a), _end_ = (b); i < _end_; ++i) 
 9 #define debug(...) fprintf(stderr, __VA_ARGS__) 
10 #define mp make_pair 
11 #define x first 
12 #define y second 
13 #define pb push_back 
14 #define SZ(x) (int((x).size())) 
15 #define ALL(x) (x).begin(), (x).end() 
16 template<typename T> inline bool chkmin(T &a, const T &b) { 
17     return a > b ? a = b, 1 : 0; 
18 } 
19 template<typename T> inline bool chkmax(T &a, const T &b) { 
20     return a < b ? a = b, 1 : 0; 
21 } 
22 typedef long long LL; 
23 const int oo = 0x3f3f3f3f; 
24 const int Mod = 9973; 
25 const int maxn = 100000; 
26 int n, ml[maxn + 5], ny[maxn + 5], l, r; 
27 char s[maxn + 5]; 
28 inline int fpm(int b, int e, int m) { 
29     LL t = 1; 
30     for ( ; e; e >>= 1, (b *= b) %= m) if (e & 1) (t *= b) %= m; 
31     return t; 
32 } 
33 int inv[Mod]; 
34 int main() { 
35     REP(i, 1, Mod) inv[i] = fpm(i, Mod - 2, Mod); 
36     while (~scanf("%d", &n)) { 
37         scanf("%s", s + 1); 
38         ml[0] = ny[0] = 1; 
39         int nn = strlen(s + 1); 
40         for (int i = 1; i <= nn; i++) { 
41             ml[i] = ml[i - 1] * (s[i] - 28) % Mod; 
42             ny[i] = inv[ml[i]]; 
43         } 
44         for (int i = 1; i <= n; i++) { 
45             scanf("%d%d", &l, &r); 
46             printf("%d\n", ml[r] * ny[l - 1] % Mod); 
47         } 
48     } 
49     return 0; 
50 } 
View Code

 

Problem D

Problem Description

度熊所居住的 D 国,是一个完全尊重人权的国度。以至于这个国家的所有人命名自己的名字都非常奇怪。一个人的名字由若干个字符组成,同样的,这些字符的全排列的结果中的每一个字符串,也都是这个人的名字。例如,如果一个人名字是 ACM,那么 AMC, CAM, MAC, MCA, 等也都是这个人的名字。在这个国家中,没有两个名字相同的人。

度熊想统计这个国家的人口数量,请帮助度熊设计一个程序,用来统计每一个人在之前被统计过多少次。

Input

这里包括一组测试数据,第一行包含一个正整数NN,接下来的NN 行代表了 NN 个名字。NN 不会超过1,000,0041,000,004,他们的名字不会超过40位.

Output

对于每输入的一个人名,输出一个整数,代表这个人之前被统计了多少次。

Sample Input
5
ACM
MAC
BBA
ACM
BAB
Sample Output
0
1
0
2
1

 1 #include <iostream>
 2 #include <map>
 3 #include <algorithm>
 4 #include <string>
 5 using namespace std;
 6 map <string, int> mymap;
 7 int n;
 8 string str;
 9 int main(){
10     cin >> n;
11     for(int i = 0; i < n; i ++){
12         cin >> str;
13         sort(str.begin(), str.end());
14         cout << mymap[str] << endl;
15         mymap[str] ++;
16         
17     }
18 }
View Code

 

}//仓鼠区over

 

*/

 

/**********************************************************************************

树形DP两道:

2012 Multi-University #9 How to paint a tree

Manthan, Codefest 16  F - The Chocolate Spree

                      ---Running_Time

***********************************************************************************/

 

/*halfapri , 哈哈哈哈哈

1 .百度之星资格赛C 

主要就是提供一份规范的板子

2 .2012多校第8场E One hundred layer (单调队列优化dp)

题解

单调队列能干啥?

答:维护一个符合某种特性的区间的最值;

怎么实现?

 

单调队列的优点:速度快O(n) ,书写复杂度很低(比其他 RMQ 算法短了4倍)。

然后大家可以去试试水,

HDU 5289 Assignment连续的最大最小值之差不超过K的子序列的总个数

 

 1 #include <bits/stdc++.h>
 2 using namespace std ;
 3 typedef long long ll ;
 4 typedef long double ld ;
 5 typedef unsigned long long ull ;
 6 #ifdef _WIN32
 7 #define LLD "%I64d"
 8 #else
 9 #define LLD "%lld"
10 #endif
11 #define pi (acos(-1.0))
12 #define fi first
13 #define se second
14 #define lson (o<<1),l,mid
15 #define rson (o<<1|1),mid+1,r
16 #define MP make_pair
17 const double eps = 1e-9 ;
18 const int inf = 0x3f3f3f3f ;
19 const ll INF = (ll)4e18 ;
20 int sign(double x){return x<-eps?-1:x>eps;}
21 
22 int n , k;
23 struct NODE {
24     int id,val ;
25     NODE (int _id=0,int _val=0):id(_id),val(_val){}
26 } ;
27 
28 void solve (int l=0) {
29     ll ret = 0 ;
30     deque<NODE> q1 , q2 ;
31     for (int i=0 ; i<n ; i++) {
32         int x ;
33         scanf ("%d" , &x) ;
34         while (!q1.empty() && x>q1.back().val) q1.pop_back();
35         q1.push_back (NODE(i,x)) ;
36         while (!q2.empty() && x<q2.back().val) q2.pop_back();
37         q2.push_back (NODE(i,x)) ;
38         while (!q1.empty()&&!q2.empty()&&
39                 q1.front().val-q2.front().val>=k) { 
40             if(q1.front().id<q2.front().id)  {
41                 l = q1.front().id+1 ;
42                 q1.pop_front() ;
43             }
44             else { 
45                 l = q2.front().id+1 ;
46                 q2.pop_front() ;
47             }
48         }
49         //printf ("[%d , %d]\n" , l,i) ;
50         ret += 1ll*(i-l+1) ;
51     }
52     printf (LLD "\n" , ret) ;
53 }
54 
55 int main () {
56     int CASE ;
57     scanf ("%d" , &CASE) ;
58     while (CASE --) {
59         scanf ("%d%d" , &n,&k) ;
60         solve () ;
61     }
62     return 0 ;
63 }
View Code

 

(2015多校第1场1002,当年是进爷A的,14级好像都不会吧==)

3.POJ2559 Largest Rectangle in a Histogram(单调栈)

题解

是不是很简单?

就去做做另一题:

hdu 5288 OO’s Sequence : f(l , r) :表示l , r这个区间内符合性质x的a(i)的数量 ;

            x性质: a(i) 满足 a(i) % a(j) != 0 ,  j != i , l <= j <= r ;

好怀念,当初我多校做出的第一道题,,,,,好吧,其实是和欣爷一起搞的。

(我发现一个梗,去年多校第一场的1001是单调栈,1002是单调队列,这是那场最简单的两题,当时14级貌似全死光了==,15级的孩子要小心啊。。。。)

4 . ST 算法 (dp ....)

给出一个长度为 n 的序列,一个若干次询问(~ 1e6) , 每次询问求一个区间的最值;

dp( i , j) : 表示在[ i , i+(1<<j)-1 ]的最值

转移:dp(i , j) = mx (dp(i , j-1) , dp(i + (1<<j) , j-1)) ;

比如说我们现在要求[l , r]的 mx ;

int k = log2(r-l+1) = (int) ( log(1.0*(r-l+1)) / log(2.0) ;//在C++里log 就是 ln , 及以自然数为底

所以答案就是 mx (dp(i , k) , dp(i-(1<<k)+1 , k) ;

*/ hahahahahahahahaha

 

 

posted @ 2016-05-14 15:07  zstuACM  阅读(290)  评论(0编辑  收藏  举报