山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 3809 Gty的二逼妹子序列(莫队算法,块状链表)

 

【题意】

 

    回答若干个询问,(l,r,a,b):区间[l,r]内权值在[a,b]的数有多少[种]。

 

【思路】

 

    考虑使用块状链表实现莫队算法中的插入与删除。

    因为权值处于1..n之间,所以我们可以建一个基于权值的块状链表,每个块维护一个区间信息sum,表示权值在该块的数的种数。

    这样插入与删除只需要O(1)的时间,查询需要O(sqrt(n))的时间,总的时间复杂度为O(n^1.5+qn^0.5)

 

【代码】

 

 1 #include<set>
 2 #include<cmath>
 3 #include<queue>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
11 using namespace std;
12 
13 typedef long long ll;
14 const int N = 3e5+10;
15 
16 ll read() {
17     char c=getchar();
18     ll f=1,x=0;
19     while(!isdigit(c)) {
20         if(c=='-') f=-1; c=getchar();
21     }
22     while(isdigit(c))
23         x=x*10+c-'0',c=getchar();
24     return x*f;
25 }
26 
27 int n,m,B;
28 int pos[N],sum[N],cnt[N],a[N],ans[N];
29 
30 struct Node 
31 {
32     int id,l,r,a,b;
33     bool operator < (const Node& rhs) const 
34     {
35         return pos[l]<pos[rhs.l]||(pos[l]==pos[rhs.l]&&r<rhs.r);
36     }
37 } q[N];
38 
39 void upd(int x,int v)
40 {
41     cnt[x]+=v;
42     if(v==1&&cnt[x]==1) sum[pos[x]]++;
43     if(v==-1&&cnt[x]==0) sum[pos[x]]--; 
44 }
45 int query(int l,int r)
46 {
47     int bl=pos[l],br=pos[r];
48     int ans=0;
49     if(bl==br)
50     {
51         FOR(i,l,r) ans+=cnt[i]>0;
52         return ans;
53     }
54     FOR(i,bl+1,br-1) ans+=sum[i];
55     bl=B*bl;
56     br=B*(br-1)+1;
57     FOR(i,l,bl) ans+=cnt[i]>0;
58     FOR(i,br,r) ans+=cnt[i]>0;
59     return ans;
60 }
61 
62 int main()
63 {
64     n=read(),m=read();
65     FOR(i,1,n) a[i]=read();
66     B=sqrt(n+0.5);
67     FOR(i,1,n) pos[i]=(i-1)/B+1;
68     FOR(i,1,m)
69     {
70         q[i].l=read(),q[i].r=read();
71         q[i].a=read(),q[i].b=read();
72         q[i].id=i;
73     }
74     sort(q+1,q+m+1);
75     int l=1,r=0;
76     FOR(i,1,m) 
77     {
78         while(l<q[i].l) upd(a[l++],-1);
79         while(l>q[i].l) upd(a[--l],1);
80         while(r<q[i].r) upd(a[++r],1);
81         while(r>q[i].r) upd(a[r--],-1);
82         ans[q[i].id]=query(q[i].a,q[i].b);
83     }
84     FOR(i,1,m)
85         printf("%d\n",ans[i]);
86     return 0;
87 }

 

posted on 2016-04-01 16:30  hahalidaxin  阅读(344)  评论(0编辑  收藏  举报