[NOI2017]蚯蚓排队
首先一看题目,感觉条件很多,很不可做,但是,经过仔细分析,其实这一道题目并不是很难。看到其中 1 和 2 的操作说白了就是向一个序列中插入或者是删除一个元素,所以实现 1 和 2 这两个操作的最佳方法就是链表了:数组是易于修改的序列存储方案,而链表是易于插入和修改的存储方案
之后我们还发现还剩下一个 3 操作我们还没有解决,仔细分析,突然发现:
k为啥这么小???
这时擅长暴力朴素算法的小伙伴咧开了笑容,对于这 \(k<=50\) ,我们完全可以使用暴力解决,所以 code:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#define int unsigned long long
using namespace std;
inline int get()
{
int s = 0,f = 1;
register char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch))
{
s = s* 10 + ch - '0';
ch = getchar();
}
return s * f;
}
inline void openfile()
{freopen("t.txt","r",stdin);}
namespace xin
{
#define s(name) cout<<sizeof(name) / (1 << 20)<<"MB"<<endl
#define ull unsigned long long
const int maxn = 12456791;
const int mod = 998244353;
int k,n,m,l[maxn],lst[maxn],nxt[maxn];
unsigned long long p[maxn];
int base = 131;
class xin_hash_table
{
public:
int cnt[maxn];
ull k[maxn];
inline void insert(ull x,int val)
{
int loc = x % maxn;
while(1)
{
if(k[loc] == 0 or k[loc] == x)
{cnt[loc] += val;k[loc] = x;break;}
loc++; if(loc == maxn) loc = 0;
}
}
inline int count(register ull x)
{
int loc = x % maxn;
while(1)
{
if(k[loc] == 0 or k[loc] == x)
return cnt[loc];
loc++; if(loc == maxn) loc = 0;
}
}
}hashtable;
ull tmp;
inline void merge(register int x,register int y)
{
int t = 48, loc = x;
while (t-- && lst[loc]) loc = lst[loc];
lst[y] = x, nxt[x] = y;
for (; lst[loc] != x; loc = nxt[loc]) {
bool flag = 0; t = loc; tmp = 0;
for (int j = 1; j <= 50 && t; j++, t = nxt[t]) {
tmp = tmp*base+l[t];
if (flag) hashtable.insert(tmp, 1);
if (t == x) flag = 1;
}
}
}
inline void cut(register int x)
{
int t = 48, loc = x; int y = nxt[x];
while (t-- && lst[loc]) loc = lst[loc];
for (; lst[loc] != x; loc = nxt[loc]) {
bool flag = 0; t = loc; tmp = 0;
for (int j = 1; j <= 50 && t; j++, t = nxt[t]) {
tmp = tmp*base+l[t];
if (flag) hashtable.insert(tmp, -1);
if (t == x) flag = 1;
}
}
lst[y] = nxt[x] = 0;
}
char ch[maxn];
inline int query()
{
int l = strlen(ch+1),ans = 1; tmp = 0;
for(register int i=1;i<=l;++i)
{
tmp = tmp * base + ch[i] - 48;
if(i > k)
tmp -= 1ll * (ch[i-k] - 48)* p[k];
if(i >= k)
ans = 1ll * (ans * hashtable.count(tmp)) % mod;
}
return ans;
}
inline short main()
{
// openfile();
n = get(); m = get(); p[0] = 1;
for(register int i=1;i<=n;++i) l[i] = get(),hashtable.insert(l[i],1);
for(register int i=1;i<=50;++i) p[i] = p[i-1] * base;
while( m--)
{
register int op = get();
if(op == 1)
{
register int x = get(),y = get();
merge(x,y);
}
if(op == 2)
{
register int x = get();
cut(x);
}
if(op == 3)
{
scanf("%s",ch+1); k = get();
printf("%d\n",query());
}
}
return 0;
}
}
signed main() {return xin::main();}
修改了 \(\LaTeX\),望通过。