zoukankan      html  css  js  c++  java
  • 分块 不同数

    注意:就算冲突了也要修改我们的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
    ", 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
    ",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
    ",ret); 
    78         }
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    sql-server数据库中利用触发器实现表与表之间的级联删除
    求任意长度数组的最大值(整数类型)。利用params参数实现任意长度的改变。
    params参数的调用
    C# 参考之方法参数关键字:params、ref及out
    写一个方法求数组中的最大值,最小值,总和以及平均值。
    写一个方法来解析一元二次方程。
    创建一个方法来判断是否为闰年。。
    构造方法
    总结重写和重载区别
    DelegatingActionProxy
  • 原文地址:https://www.cnblogs.com/chxer/p/4420560.html
Copyright © 2011-2022 走看看