codechef Chef and Problems

终于补出这道:一直耽搁到现在

找到一个代码可读性很好的分块temp;

题意:给一个长度为n 的数组 A,Q次询问,区间相等数的最大范围是多少?

数据范围都是10e5;

当然知道分块了;

传统分块看各种累;

找了一份很好的tmp<新技能get;

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 const int N =100005;
 5 const int S =405;
 6 
 7 int a[N],res[S][N],occ[N];
 8 int ans[N];
 9 //一种很神奇的分块写法
10 //想办法 在其他题目扩展
11 
12 struct query
13 {
14     int L,R,id;
15     bool operator <(const query& a)const
16     {
17         return R<a.R;
18     }
19 }q[N];
20 
21 int main()
22 {
23     int n,m,k;
24     scanf("%d%d%d",&n,&m,&k);
25     int s=sqrt(n);
26     for (int i=0;i<n;i++) scanf("%d",&a[i]);
27 
28     for (int i=0;i*s<n;i++)//预处理0-->sqrt(n)个块,每块的宽度这里并不一定相同
29     {                       //这里是从i*s-->n 都计算出区间的最大值
30         for (int j=1;j<=m;j++) occ[j]=-1;
31         int now=0;
32         for (int j=i*s;j<n;j++)
33         {
34             if (occ[a[j]]==-1) occ[a[j]]=j;
35             else now=max(now,j-occ[a[j]]);
36             res[i][j]=now;
37         }
38     }
39 
40     for (int i=0;i<k;i++)
41     scanf("%d%d",&q[i].L,&q[i].R),q[i].id=i,q[i].L--,q[i].R--;
42     sort(q,q+k);//按询问R排序
43     
44     
45     for (int i=1;i<=m;i++)
46         occ[i]=-1;
47 
48     int r=0;
49 
50     for (int i=0;i<k;i++)
51     {
52         while (r<q[i].R)//q[i].L<q[i].R;
53         {
54             ++r;
55             occ[a[r]]=r;//预处理出前几个
56         }
57 
58         int tmp=res[q[i].L/s+1][q[i].R];//计算已经可以分块的数据
59         for (int j=q[i].L;j<(q[i].L/s+1)*s&&j<=q[i].R;j++)
60         tmp=max(tmp,occ[a[j]]-j);//利用询问的单调询问开始不足一块的数据
61         ans[q[i].id]=tmp;
62     }
63 
64     for (int i=0;i<k;i++) printf("%d\n",ans[i]);
65     return 0;
66 }

 

posted on 2015-05-26 01:53  forgot93  阅读(299)  评论(0编辑  收藏  举报

导航