[NOI2017]蚯蚓排队 - hash + 暴力

经过一通复杂度分析后发现,只要暴力做就可以了

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <cstring>
  5 #include <algorithm>
  6 #define LL long long
  7 
  8 using namespace std;
  9 
 10 inline LL read()
 11 {
 12     LL x = 0, w = 1; char ch = 0;
 13     while(ch < '0' || ch > '9') {
 14         if(ch == '-') {
 15             w = -1;
 16         }
 17         ch = getchar();
 18     }
 19     while(ch >= '0' && ch <= '9') {
 20         x = x * 10 + ch - '0';
 21         ch = getchar();
 22     }
 23     return x * w;
 24 }
 25 const int MOD = 998244353;
 26 const int MAXS = 1e7 + 10;
 27 const int MAXN = 2e5 + 10;
 28 const int K = 51;
 29 const int mod = 10233333;
 30 
 31 int n, m;
 32 
 33 char s[MAXS];
 34 unsigned LL pre[K * 10], g1[K * 10], g2[K * 10];
 35 int num[MAXN];
 36 int nex[MAXN], ppr[MAXN];
 37 
 38 void init()
 39 {
 40     pre[0] = 1;
 41     for(int i = 1; i <= K; i++) {
 42         pre[i] = pre[i - 1] * 19260817;
 43     }
 44 }
 45 
 46 int tot = 0;
 47 
 48 struct str {
 49     unsigned LL x;
 50     LL num;
 51     int next;
 52 } tmp, e[21000000];
 53 
 54 struct hashtable {
 55     int head[mod];
 56     void add(unsigned LL x, int k)
 57     {
 58         int s = x % mod;
 59         for(int i = head[s]; i; i = e[i].next) {
 60             if(e[i].x == x) {
 61                 e[i].num += k;
 62                 return;
 63             }
 64         }
 65         e[++tot].num = k, e[tot].x = x;
 66         e[tot].next = head[s];
 67         head[s] = tot;
 68     }
 69     LL cal(unsigned LL x)
 70     {
 71         int s = x % mod;
 72         for(int i = head[s]; i; i = e[i].next) {
 73             if(e[i].x == x) {
 74                 return e[i].num;
 75             }
 76         }
 77         return 0;
 78     }
 79 } h;
 80 
 81 inline void merge(int a, int b)
 82 {
 83     int l = 0, r = 0;
 84     for(int i = a; i && l < K; i = ppr[i]) {
 85         g1[++l] = g1[l - 1] + num[i] * pre[l - 1];
 86     }
 87     for(int i = b; i && r < K; i = nex[i]) {
 88         g2[++r] = g2[r - 1] * 19260817 + num[i];
 89     }
 90     for(int i = 1; i <= l; i++) {
 91         for(int j = 1; j <= r; j++) {
 92             if(i + j > K) 
 93                 break; 
 94             
 95             h.add(g1[i] * pre[j] + g2[j], 1);
 96         }
 97     }
 98     nex[a] = b, ppr[b] = a;
 99 }
100 
101 inline void split(int a)
102 {
103     int b = nex[a];
104     int l = 0, r = 0;
105     for(int i = a; i && l < K; i = ppr[i]) {
106         g1[++l] = g1[l - 1] + num[i] * pre[l - 1];
107     }
108     for(int i = b; i && r < K; i = nex[i]) {
109         g2[++r] = g2[r - 1] * 19260817 + num[i];
110     }    
111     for(int i = 1; i <= l; i++) {
112         for(int j = 1; j <= r; j++) {
113             if(i + j > K) 
114                 break;
115             h.add(g1[i] * pre[j] + g2[j], -1);
116         }
117     }
118     nex[a] = 0, ppr[b] = 0;
119 }
120 
121 void query()
122 {
123     int sum = 0;
124     scanf("%s", s + 1);
125     int k = read();
126     int len = strlen(s + 1);
127     unsigned LL ha = 0;
128     int ans = 1;
129 //    cout<<k<<endl;
130     for(register int i = 1; i <= len; i++) {
131         ha = ha * 19260817 + s[i] - '0';
132         if(i >= k) {
133         //    cout<<ha<<" "<<h.cal(ha)<<endl;
134             ans = 1ll * ans * h.cal(ha) % MOD;
135         //    cout<<s[i] - '0'<<" "<<(s[i - k + 1] - '0')<<" "<<ha<<endl;
136             ha = ha - (s[i - k + 1] - '0') * pre[k - 1];
137         }
138     }    
139     printf("%d\n", ans);
140 }
141 
142 int main()
143 {
144 //    freopen("testdata.in", "r", stdin);
145 //    freopen("worm.out", "w", stdout);
146     init();
147     n = read(), m = read();
148     for(int i = 1; i <= n; i++) {
149          num[i] = read();
150          h.add(num[i], 1);
151     }
152     for(int i = 1; i <= m; i++) {
153         int opr = read();
154         if(opr == 1) {
155             int a = read(), b = read();
156             merge(a, b);
157         } else if(opr == 2) {
158             int a = read();
159             split(a);
160         } else {
161             query();
162         }
163     }
164 }
165 
166 /*
167 
168 2 2
169 6 6
170 1 1 2
171 3 666666 4
172 
173 */
View Code

 

转载于:https://www.cnblogs.com/wuenze/p/9255911.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值