BestCoder#27 2015/1/24
前面的基本思路来自hdu的官网解答
1001 Jump and Jump...
首先算出每个人的成绩,然后sort一下就好了,考虑
n
的范围只有2或者3,只要用if+swap也是可行的。
1002 Taking Bus
题目大意:
给你一个线路上的站点个数和站点之间的距离,根据发车的个数确定发车站点,再根据上车人的站点和目的地计算出时间,车从左往右然后折返着开,一个单位距离用一秒
输入输出样例:
输入样例
1 (T-组数)
7 3(7为n,表示站点数;3为m,乘车人数)
2 3 4 3 4 5 (七个站之间的距离)
1 7(第一个人,从站1到站7,出发站为1)
4 5(第二个人,从站1到站7,出发站为2)
5 4(始发站是这么算的:第i个人的话,始发站为(i-1)mod n +1)
输出样例
21
10
28
提示:
对于第一个人, 公交在站点1出发, 然后这个人在时刻0上车。21秒之后,公交到达站点7。
对于第二个人,公交在站点2出发。7秒之后,公交到达站点4,这个人上车。之后又过了3秒,公交到达站点5.总共用了10秒。
对于第三个人,公交在站点3出发。7秒之后,公交到达站点5,这个人上车。之后过了9秒,公交达到站点7,然后转向开往站点0。之后经过12秒,公交达到站点4。因此总共需要28秒时间。
简单的分类讨论,设
s,x,y
分别表示公交的始发站,起点和终点。大概有这样几种情况:1.
s≤x<y
, 2.
x<s<y
,3.
x<y≤s
, 4.
s≤y<x
, 5.
y<s<x
, 6.
y<x≤s
分别写出公式即可。答案应该会超过int,注意要用long long。
解题思路:
首先是分情况讨论,其次呢,关于怎么计算一段路程的长度,这个呢,我们很容易联想到线段树的干活,其实除了线段树,还有一个简单方法,就是开一个distance[]数组,distance[i]=前i个点的距离,那么i-j的距离不就是distance[j]-distance[i]吗
经验总结:
注意取值的大小,我就是因为一开始没有注意long long的问题所以wrong answer了!
#include
#include
#include
#include
#define maxn 100003
using namespace std;
long long int vals ;
long long int val[maxn] ;
struct line
{
int left,right ;
long long int sum ;
}a[maxn*4];
void buil ( int l , int r , int n )
{
int mid ;
a[n].left = l ;
a[n].right = r ;
if( l == r-1 ) {
a[n].sum = val[l] ;
return ;
}
mid = ( l + r ) / 2 ;
buil( l , mid , 2*n ) ;
buil( mid , r , 2*n+1 ) ;
a[n].sum = a[2*n].sum + a[2*n+1].sum ;
}
long long int getval ( int i , int j ,int start )
{
int mid ;long long int sum = 0 ;
if( i == j ){
return 0;
}
if( a[start].left == i && a[start].right== j ){
return a[start].sum ;
}
mid = ( a[start].left + a[start].right )/2 ;
if( mid >= j ){
sum += getval( i , j , 2*start ) ;
}
else{
if( mid <= i ){
sum += getval( i , j , 2*start+1 ) ;
}
else{
sum += getval( i , mid , 2*start ) ;
sum += getval( mid , j , 2*start+1 ) ;
}
}
return sum ;
}
int main()
{
int T,n,m;
int s1,s2,ss;
int ju1,ju2;
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
for(int i = 1 ; i
1003 Matching on Array
题目大意:
给你一个Alice串,很长的整数串,给你一堆Bob串,很多个整数串,问Alice串里有几个Bob串出现,这里出现定义为存在一个Alice的连续子串,其前后比例与Bob串相同,比如2 4 6 8 的Alice串,1 2 4 的Bob串,那么2 4 6 就与1 2 4 匹配
输入输出样例:
输入样例
2(组数T)
4 1(Alice串长,Bob串个数)
2 4 8 16(alice 串)
2 1 2(Bob串长 Bob串)
5 3
2 4 2 4 6
3 1 2 1
1 5
2 16 8
输出样例
3(2 4 4 8 8 16 共3个)
7
首先我们考虑
m=1
的情况。给定两个数组
A={a1,a2,…,an}
和
B={b1,b2,…,bk}
,问
B
在
A
中出现了几次。令
ci=ai+1ai,1≤i<n
,同样令
di=bi+1bi,1≤i<k
,那么上述问题可以转化为
ci
和
di
的模式匹配问题,这个正确性显然,也没有什么好证明的。于是对于
m=1
的情况只有用个kmp即可搞定。现在考虑
m>1
的情况,我们考虑用ac自动机来做。考虑到字符集并不是普通的数字,而是一个分数,我们不放搞个分数类,然后用map存转移边。用
m
个模式串(Bob的序列)建好自动机之后,把文本串(Alice的序列)在自动机上跑一遍即可统计出答案。
解题思路:
首先,我们得有个问题转化,不是求一个子串C,满足 C与Bob子串成比例吗,那么我们就有:c2/b2 = c1/b1;这其实就转成:c2/c1 = b2/b1; c3/c2 = b3/b2 那么Bob子串就可以转化成比例串了
最后其实就是一个ac自动机变形题,不过这个变形还挺巧妙的,我们把储存的字符串变成比例,而这样的改变也会使得我们固定的26的空间大小发生改变,为此,我们利用map来解决
1. 利用map的关键字,我们可以不固定每个比例值的分支个数和数值
2. 关键字的选取:比如比例为 b1 b2 那么 b2/b1的值就记为b2/gcd(b1,b2)*100001+b1,可以证明,这个关键字独一无二
经验总结:
此题很棒啊,不过由于是ac自动机的变形,所以很多东西都要转化过来,比如map数组mp,mp[i]相当于第i个节点,map[i][j]相当于第i个节点比例为j的那个子节点,其值为子节点的序号
【本代码,来自http://blog.csdn.net/u013368721/article/details/43118531的分享】
#include
#include