【BZOJ 2119】 2119: 股市的预测 (后缀数组+分块+RMQ)

2119: 股市的预测

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 404  Solved: 188

Description

墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势。股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰地展示了股票的走势情况。经过长时间的观测,墨墨发现很多股票都有如下的规律:之前的走势很可能在短时间内重现!如图可以看到这只股票A部分的股价和C部分的股价的走势如出一辙。通过这个观测,墨墨认为他可能找到了一个预测股票未来走势的方法。进一步的研究可是难住了墨墨,他本想试图统计B部分的长度与发生这种情况的概率关系,不过由于数据量过于庞大,依赖人脑的力量难以完成,于是墨墨找到了善于编程的你,请你帮他找一找给定重现的间隔(B部分的长度),有多少个时间段满足首尾部分的走势完全相同呢?当然,首尾部分的长度不能为零。

Input

输入的第一行包含两个整数N、M,分别表示需要统计的总时间以及重现的间隔(B部分的长度)。接下来N行,每行一个整数,代表每一个时间点的股价。

Output

输出一个整数,表示满足条件的时间段的个数

Sample Input

12 4
1 2 3 4 8 9 1 2 3 4 8 9

Sample Output

6
【样例说明】
6个时间段分别是:3-9、2-10、2-8、1-9、3-11、4-12。

HINT

对于100%的数据,4≤N≤50000 1≤M≤10 M≤N 所有出现的整数均不超过32位含符号整数。

Source

 

 

【分析】

  做差之后就是UVU式的题,就是像UVA10829那题了。

  所以可以看那个题解。

  然后我觉得我那时候智障。。。while找的话其实nlogn就没用了,变成了n^2,也不知道我当时看谁的。

  但是亲测,一边sa一边while可过,两边while不可过。

  但是太迷了,我把它改成了两边sa了。比之前就快了很多。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxl 50010
  9  
 10 int l,pp;
 11 int c[Maxl],cl;
 12  
 13 int mymin(int x,int y) {return x<y?x:y;}
 14  
 15 struct node {int x,id;}t[Maxl];
 16 bool cmp(node x,node y) {return x.x<y.x;}
 17  
 18 void init()
 19 {
 20     scanf("%d%d",&cl,&l);
 21     int bf;
 22     scanf("%d",&bf);
 23     for(int i=2;i<=cl;i++)
 24     {
 25         int x;
 26         scanf("%d",&x);
 27         t[i-1].x=x-bf;t[i-1].id=i-1;
 28         bf=x;
 29     }cl--;
 30     sort(t+1,t+1+cl,cmp);
 31     pp=1;c[t[1].id]=1;
 32     for(int i=2;i<=cl;i++)
 33     {
 34         if(t[i].x!=t[i-1].x) pp++;
 35         c[t[i].id]=pp;
 36     }
 37 }
 38  
 39 int sa[Maxl],rk[Maxl],y[Maxl],wr[Maxl],Rs[Maxl];
 40 void get_sa(int m)
 41 {
 42     memcpy(rk,c,sizeof(rk));
 43     for(int i=1;i<=m;i++) Rs[i]=0;
 44     for(int i=1;i<=cl;i++) Rs[rk[i]]++;
 45     for(int i=2;i<=m;i++) Rs[i]+=Rs[i-1];
 46     for(int i=cl;i>=1;i--) sa[Rs[rk[i]]--]=i;
 47      
 48     int ln=1,p=0;
 49     while(p<cl)
 50     {
 51         int k=0;
 52         for(int i=cl-ln+1;i<=cl;i++) y[++k]=i;
 53         for(int i=1;i<=cl;i++) if(sa[i]>ln) y[++k]=sa[i]-ln;
 54         for(int i=1;i<=cl;i++) wr[i]=rk[y[i]];
 55          
 56         for(int i=1;i<=m;i++) Rs[i]=0;
 57         for(int i=1;i<=cl;i++) Rs[wr[i]]++;
 58         for(int i=2;i<=m;i++) Rs[i]+=Rs[i-1];
 59         for(int i=cl;i>=1;i--) sa[Rs[wr[i]]--]=y[i];
 60          
 61         for(int i=1;i<=cl;i++) wr[i]=rk[i];
 62         for(int i=cl+1;i<=cl+ln;i++) wr[i]=0;
 63         p=1,rk[sa[1]]=1;
 64         for(int i=2;i<=cl;i++)
 65         {
 66             if(wr[sa[i]]!=wr[sa[i-1]]||wr[sa[i]+ln]!=wr[sa[i-1]+ln]) p++;
 67             rk[sa[i]]=p;
 68         }
 69         ln*=2,m=p;
 70     }
 71     sa[0]=rk[0]=0;
 72 }
 73  
 74 int height[Maxl];
 75 void get_he()
 76 {
 77     int k=0;
 78     for(int i=1;i<=cl;i++) if(rk[i]!=1)
 79     {
 80         int j=sa[rk[i]-1];
 81         if(k) k--;
 82         while(c[i+k]==c[j+k]&&i+k<=cl&&j+k<=cl) k++;
 83         height[rk[i]]=k;
 84     }
 85 }
 86  
 87 int d[2][Maxl][20];
 88 void rmq_init(int p)
 89 {
 90     for(int i=1;i<=cl;i++) d[p][i][0]=height[i];
 91     for(int j=1;(1<<j)<=cl;j++)
 92       for(int i=1;i+(1<<j)-1<=cl;i++)
 93         d[p][i][j]=mymin(d[p][i][j-1],d[p][i+(1<<j-1)][j-1]);
 94 }
 95  
 96 int rq[2][Maxl];
 97 int rmq(int x,int y,int p)
 98 {
 99     int t;
100     x=rq[p][x];y=rq[p][y];
101     if(x>y) swap(x,y);
102     x++;
103     int k=0;
104     while((1<<k+1)<=y-x+1) k++;
105     return mymin(d[p][x][k],d[p][y-(1<<k)+1][k]);
106 }
107  
108  
109 void ffind()
110 {
111     int ans=0;
112     for(int i=1;i<=cl;i++)
113     {
114         for(int j=0;j<=cl/i;j++)
115         {
116             int now=j*i+1,x=1,y=0;
117             if(now+l+i>cl) continue;
118             x=mymin(i,rmq(now,now+l+i,0));
119             y=mymin(i-1,rmq(cl-(now+l+i-1)+1,cl-(now-1)+1,1));
120             if(x+y-i+1>0&&x!=0) ans+=x+y-i+1;
121         }
122     }
123     printf("%d\n",ans);
124 }
125  
126 int cc[Maxl];
127  
128 int main()
129 {
130     init();
131     get_sa(pp);for(int i=1;i<=cl;i++) rq[0][i]=rk[i];
132     get_he();rmq_init(0);
133     for(int i=1;i<=cl;i++) cc[i]=c[cl-i+1];
134     for(int i=1;i<=cl;i++) c[i]=cc[i];                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
135     get_sa(pp);
136     for(int i=1;i<=cl;i++) rq[1][i]=rk[i];
137     get_he();
138     rmq_init(1);
139     ffind();
140     return 0;
141 }
View Code

 

2017-03-24 14:42:24

转载于:https://www.cnblogs.com/Konjakmoyu/p/6611445.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值