zoukankan      html  css  js  c++  java
  • [NOI2017]蚯蚓排队 hash

    题面:洛谷

    题解:

      我们暴力维护当前所有队伍内的所有子串(长度k = 1 ~ 50)的出现次数。

      把每个子串都用一个hash值来表示,每次改变队伍形态都用双向链表维护,并暴力更新出现次数。

      现在考虑复杂度。

      如果只有连接,没有断开,那么复杂度为不同的子串个数:50n(注意只要O(n)预处理前缀和后缀hash就可以做到O(1)得到一个子串的hash值)

      如果有断开,那么最多就每断开一次就对应要再重连一次。所以复杂度最多增加2500 * 断开次数,而断开次数1e3....

      所以复杂度就是正确的了。

      此题略卡常。

      如果T了一两个点,,,就多交几次吧,,,说不定哪次就过了呢?

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 201000
      5 #define ac 10501000
      6 #define LL long long
      7 #define us unsigned
      8 #define maxn 49//每边最多49个,以为另外一边至少一个
      9 #define base 19260817//2333//直接用10???
     10 #define bu 16777215//49999991//100000081//cket 一个质数,,,
     11 #define mod 998244353
     12 #define h(f) (f & bu)
     13 
     14 int n, m, top;
     15 int v[AC], last[AC], Next[AC];
     16 us LL hs[AC], ls[ac], p[ac];
     17 int Head[ac * 3], Next1[ac], date[ac], tot, id;
     18 int cnt[ac]; us LL power[ac];//存下每个id对应的hash值以及出现次数
     19 int s[AC];
     20 char ss[ac];
     21 //int tot, id;
     22 
     23 #define Next Next1
     24 //inline int h(int f){
     25     //return (((f & bu) ^ (mod >> 5)) + 1);
     26 //}
     27 
     28 struct node{
     29     
     30     inline void add(int f, us LL x)
     31     {//如果x这个表上没有k这个值,那就要新开id,否则直接用原来的id
     32     //    printf("%d %llu
    ", f, x);
     33     //    printf("%llu
    ", x);
     34         for(R i = Head[f]; i; i = Next[i])
     35             if(power[date[i]] == x) {++ cnt[date[i]]; return ;}
     36         int tmp = ++ id;
     37         date[++ tot] = tmp, Next[tot] = Head[f], Head[f] = tot;
     38         power[tmp] = x, cnt[tmp] = 1;
     39     }
     40     
     41     inline void del(int f, us LL x)//找到这个值并删除一个
     42     {
     43         for(R i = Head[f]; i; i = Next[i])
     44             if(power[date[i]] == x) {-- cnt[date[i]]; return ;}
     45     }
     46     
     47     inline int find(int f, us LL x)
     48     {
     49         for(R i = Head[f]; i; i = Next[i])
     50             if(power[date[i]] == x) return cnt[date[i]];
     51         return 0;
     52     }
     53 }T;
     54 #undef Next
     55 
     56 inline int read()
     57 {
     58     int x = 0;char c = getchar();
     59     while(c > '9' || c < '0') c = getchar();
     60     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     61     return x;
     62 }
     63 
     64 void pre()
     65 {
     66     n = read(), m = read(), p[0] = 1;
     67     for(R i = 1; i <= n; i ++) v[i] = read(), T.add(h(v[i]), v[i]);//先把单个的加进去
     68     for(R i = 1; i <= n; i ++) p[i] = p[i - 1] * base;//自然溢出
     69 }
     70 
     71 us LL cal(int l, int r){//返回[l, r]的hash值
     72     return ls[r] - ls[l - 1] * p[r - l + 1];
     73 }
     74 
     75 void get_hs(int mid, bool z)//获取所有长度<= 50的,跨mid的hs值
     76 {
     77     for(R i = 1; i <= top; i ++) ls[i] = ls[i - 1] * base + s[i];
     78     for(R i = 1; i <= mid; i ++)//枚举开头
     79     {
     80         int lim1 = mid - i + 2, lim2 = top - i + 1;//长度要在[lim1, lim2]的范围内
     81         for(R len = lim1; len <= lim2; len ++)//才能保证合法
     82         {
     83             int r = i + len - 1;
     84             us LL x = cal(i, r);//获取区间hash值
     85             if(z) T.add(h(x), x);
     86             else T.del(h(x), x);
     87         }
     88     }
     89 }
     90 
     91 void link1()//每次合并的时候暴力加hash值,每次最多增加1250个
     92 {
     93     int x = read(), y = read(), cnt = 0, tmp = 0;//把j接到i之后
     94     Next[x] = y, last[y] = x, top = 0;
     95     for(R i = x; i && cnt < maxn; i = last[i]) ++ cnt, tmp = i;
     96     for(R i = tmp; i != x; i = Next[i]) s[++ top] = v[i];
     97     s[++ top] = v[x], cnt = top;
     98     for(R i = y; i && top - cnt != maxn; i = Next[i]) s[++ top] = v[i];
     99     get_hs(cnt, 1);
    100 }
    101 
    102 void link()//每次合并的时候暴力加hash值,每次最多增加1250个
    103 {
    104     int x = read(), y = read(), cnt = 0, tmp = 0;//把j接到i之后
    105     Next[x] = y, last[y] = x, top = 0;
    106     for(R i = x; i && cnt < maxn; i = last[i]) ++ cnt, tmp = i;
    107     for(R i = tmp; i != x; i = Next[i]) s[++ top] = v[i];
    108     s[++ top] = v[x], cnt = top;
    109     for(R i = y; i && top - cnt != maxn; i = Next[i]) s[++ top] = v[i];
    110     get_hs(cnt, 1);
    111 }
    112 
    113 void cut()//每次合并的时候暴力减hash值,每次最多减少1250个,但总体很小
    114 {
    115     int x = read(), y = Next[x], cnt = 0, tmp = 0;//把i和它之后的一个蚯蚓断开
    116     last[y] = Next[x] = top = 0;
    117     for(R i = x; i && cnt < maxn; i = last[i]) ++ cnt, tmp = i;
    118     for(R i = tmp; i != x; i = Next[i]) s[++ top] = v[i];
    119     s[++ top] = v[x], cnt = top;
    120     for(R i = y; i && top - cnt != maxn; i = Next[i]) s[++ top] = v[i];
    121     get_hs(cnt, 0);
    122 }
    123 
    124 void find()//处理hash值的时候暴力O(n)处理前缀hash值,然后查询的时候也O(n)遍历查询
    125 {//因为s长度之和最多1e7....
    126     //cin >> ss + 1, top = strlen(ss + 1);
    127     scanf("%s", ss + 1), top = strlen(ss + 1);
    128     int k = read(), b = top - k + 1;
    129     for(R i = 1; i <= top; i ++) 
    130         ls[i] = ls[i - 1] * base + ss[i] - '0';    
    131     LL ans = 1;
    132     for(R i = 1; i <= b; i ++)
    133     {
    134         us LL x = cal(i, i + k - 1);
    135         ans *= T.find(h(x), x);
    136         //printf("!!%d ", T.find(x & bu, x));
    137         if(ans > mod) ans %= mod;
    138     }
    139     //printf("
    ");
    140     printf("%lld
    ", ans);
    141 }
    142 
    143 void work()
    144 {
    145     for(R i = 1; i <= m; i ++)
    146     {
    147         int opt = read();
    148         if(opt == 1) link();
    149         else if(opt == 2) cut();
    150         else find();
    151     }
    152 }
    153 
    154 int main()
    155 {
    156 //    freopen("in.in", "r", stdin);
    157     pre();
    158     work();
    159     //fclose(stdin);
    160     return 0;
    161 }
    View Code
  • 相关阅读:
    HDU Railroad (记忆化)
    HDU 1227 Fast Food
    HDU 3008 Warcraft
    asp vbscript 检测客户端浏览器和操作系统(也可以易于升级到ASP.NET)
    Csharp 讀取大文本文件數據到DataTable中,大批量插入到數據庫中
    csharp 在万年历中计算显示农历日子出错
    csharp create ICS file extension
    CSS DIV Shadow
    DataTable search keyword
    User select fontface/color/size/backgroundColor设置 字体,颜色,大小,背景色兼容主流浏览器
  • 原文地址:https://www.cnblogs.com/ww3113306/p/10067798.html
Copyright © 2011-2022 走看看