[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\),望通过。

posted @ 2021-05-05 09:51  NP2Z  阅读(54)  评论(0编辑  收藏  举报