码迷,mamicode.com
首页 > 其他好文 > 详细

分块 不同数

时间:2015-04-12 22:35:39      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:

注意:就算冲突了也要修改我们的num,因为这个调了一下午Σ( ° △ °|||)︴

哈希链表会好一点,因为我们要的是连续的指针,就不用映射map了。(TAT)

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 #define ID bl[i]
  7 #define REP(i, s, n) for(int i = s; i <= n; i ++)
  8 #define RAP(i, n, s) for(int i = n; i >= s; i --)
  9 using namespace std;
 10 const int maxn = 100000 + 10;
 11 const int maxb = 317 + 10;
 12 int n, Q, w[maxb][maxb], bl[maxn], pre[maxn], suf[maxn], A[maxn], SIZE, st[maxn], en[maxn], cnt[156779][maxb];
 13 bool num[156779];
 14 int map[maxn], ms = 0;
 15 const int hash_max = 156779;
 16 const int hash_check = 78389;
 17 const int hash_delta = 78389;
 18 const int hash_find = 3901;
 19 struct HASH{
 20     int hash[hash_max];
 21     bool vis[hash_max];
 22     int hash_sortn(int v){
 23         v %= hash_max;
 24         if(v < 0) v += hash_max;
 25         return v;
 26     }
 27     int hash_checkn(int v){
 28         if(v & 1) { v = v % hash_check; if(v < 0) v += hash_check; }
 29         else { v = v % hash_check; if(v < 0) v += hash_check; v += hash_delta; }
 30         return v;
 31     }
 32     int hash_findn(int v){
 33         v = (v * hash_find) % hash_max;
 34         if(v < 0) v += hash_max;
 35         return v;
 36     }
 37     int find_insert(int v){
 38         int ids = hash_sortn(v);
 39         if(!vis[ids]){
 40             hash[ids] = v;
 41             vis[ids] = true;
 42             return map[++ ms] = ids;
 43         }
 44         else if(v == hash[ids]) return ids;
 45         int id = hash_checkn(v);
 46         if(!vis[id]){
 47             hash[id] = v;
 48             vis[id] = true;
 49             return map[++ ms] = id;
 50         }
 51         for(int i = id; ; i += hash_findn(i) + ids * i){
 52             i %= hash_max;
 53             if(i < 0) i += hash_max;
 54             if(!vis[i]){
 55                 hash[i] = v;
 56                 vis[i] = true;
 57                 //map[++ ms] = i;
 58                 //return ms;
 59                 return map[++ ms] = i;
 60             }
 61             else if(v == hash[i]) return i;
 62         }
 63     }
 64 }hashtable;
 65 void read(int &x){
 66     x = 0; int sig = 1; char ch = getchar();
 67     while(!isdigit(ch)) { if(ch == -) sig = -1; ch = getchar(); }
 68     while(isdigit(ch)) x = 10 * x + ch - 0, ch = getchar();
 69     x *= sig; return ;
 70 }
 71 void init(){
 72     read(n); read(Q); SIZE = (int)sqrt(n);
 73     bl[0] = bl[n + 1] = n + 1;
 74     REP(i, 1, n){
 75         read(A[i]);
 76         A[i] = hashtable.find_insert(A[i]);
 77         ID = (i - 1) / SIZE + 1;
 78         if(!st[ID]) st[ID] = i;
 79         en[ID] = i;
 80     }
 81     REP(i, 1, bl[n]){
 82         int ans = 0; memset(num, false, sizeof(num));
 83         REP(j, st[i], n){
 84             if(!num[A[j]]) ans ++;
 85             num[A[j]] = true; 
 86             w[i][bl[j]] = max(w[i][bl[j]], ans);
 87         }
 88     }
 89     REP(i, 1, bl[n]){
 90         REP(j, 1, ms) cnt[map[j]][i] = cnt[map[j]][i - 1]; 
 91         REP(j, st[i], en[i]) cnt[A[j]][i] ++;
 92     }
 93     return ;
 94 }
 95 void work(){
 96     int L, R;
 97     while(Q --){
 98         read(L); read(R); int ret = 0;
 99         if(bl[R] - 1 < bl[L] + 1){
100             memset(num, false, sizeof(num));
101             REP(i, L, R){ 
102                 if(!num[A[i]]) ret ++;
103                 num[A[i]] = true;
104             }
105         }
106         else{
107             memset(num, false, sizeof(num));
108             ret = w[bl[L] + 1][bl[R] - 1];
109             REP(i, L, en[bl[L]]){
110                 if(!num[A[i]] && cnt[A[i]][bl[R] - 1] == cnt[A[i]][bl[L]]) ret ++;
111                 num[A[i]] = true;
112             }
113             REP(i, st[bl[R]], R){
114                 if(!num[A[i]] && cnt[A[i]][bl[R] - 1] == cnt[A[i]][bl[L]]) ret ++;
115                 num[A[i]] = true;
116             }
117         }
118         printf("%d\n", ret);
119     }
120     return ;
121 }
122 void print(){
123     
124     return ;
125 }
126 int main(){
127     init();
128     work();
129     print();
130     return 0;
131 }

WZJ的哈希链表,快了300ms:

 1 #include<cctype>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 using namespace std; 
 7 inline void read(int& x)
 8 {
 9     char ch=getchar();x=0;
10     while(!isdigit(ch)) ch=getchar();
11     while(isdigit(ch)) x=x*10+ch-0,ch=getchar();
12 }
13 const int maxn=100010;
14 const int HASHSIZE=87153;
15 int head[HASHSIZE],next[maxn],v[maxn],tot;
16 int find(int val)
17 {
18     int k=val%HASHSIZE;
19     for(int x=head[k];x;x=next[x])
20         if(v[x]==val) return x;
21     v[++tot]=val;
22     next[tot]=head[k];
23     return head[k]=tot;
24 }
25 int n,m,SIZE,c[maxn],bl[maxn],st[maxn],en[maxn],cnt[10000][350],num[maxn],ans[350][350];
26 int main()
27 {
28     read(n),read(m); SIZE=(int)sqrt(n);
29     for(int i=1;i<=n;i++)
30     {
31         read(c[i]);
32         c[i]=find(c[i]);
33         bl[i]=(i-1)/SIZE+1;
34         if(!st[bl[i]]) st[bl[i]]=i;
35         en[bl[i]]=i;
36     }
37     for(int i=1;i<=bl[n];i++)
38     {
39        int tmp=0;
40        for(int j=st[i];j<=n;j++)
41        {
42            if(++num[c[j]]==1) tmp++;
43            ans[i][bl[j]]=max(ans[i][bl[j]],tmp);
44        }
45        memset(num,0,sizeof(num));
46     }
47     for(int i=1;i<=bl[n];i++)
48     {
49        for(int j=1;j<=tot;j++) cnt[j][i]=cnt[j][i-1];
50        for(int j=st[i];j<=en[i];j++) cnt[c[j]][i]++;
51     }
52     int l,r,ret;
53     while(m--)
54     {
55         read(l),read(r); ret=0;
56         if(bl[l]+1>=bl[r])
57         {
58             for(int i=l;i<=r;i++) if(++num[c[i]]==1) ret++;
59             for(int i=l;i<=r;i++) num[c[i]]=0;
60             printf("%d\n",ret);
61         }
62         else
63         {
64             ret=ans[bl[l]+1][bl[r]-1];
65             for(int i=l;i<=en[bl[l]];i++)
66             {
67                 if(!num[c[i]]&&cnt[c[i]][bl[r]-1]==cnt[c[i]][bl[l]]) ret++;
68                 num[c[i]]++;
69             }
70             for(int i=st[bl[r]];i<=r;i++)
71             {
72                 if(!num[c[i]]&&cnt[c[i]][bl[r]-1]==cnt[c[i]][bl[l]]) ret++;
73                 num[c[i]]++;
74             }
75             for(int i=l;i<=en[bl[l]];i++) num[c[i]]=0;
76             for(int i=st[bl[r]];i<=r;i++) num[c[i]]=0;
77             printf("%d\n",ret); 
78         }
79     }
80     return 0;
81 }

 

分块 不同数

标签:

原文地址:http://www.cnblogs.com/chxer/p/4420560.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!