题解 逆转函数

传送门

发现这个东西很像回文反正我没发现
那么考虑 manacher

image

这是核心操作,感觉通过维护 \(n\)\(p\) 来判断区间合法的思路并不容易想到
然后发现 manacher 的过程中还有一个 d[i]=min(d[mid*2-i], r-i+1);
这个东西在这道题里需要暴力反推直到不超 r 的范围为止

  • 一个关于 manacher d[i]=min(d[mid*2-i], r-i+1); 的小结论:
    这里写成 d[i]=d[mid*2-i]; while (d[i]>r-i+1) --d[i]; 的复杂度也是对的
    证明:
    image
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
int a[N];
const ll mod=998244353;

namespace force{
	ll pw[N], ans;
	int mp[N], sta[N], tim[N], top, now;
	ll calc(int l, int r) {
		++now;
		int len=r-l+1, cnt=0;
		for (int i=1; i<=len; ++i) {
			if (tim[a[l+i-1]]!=now) tim[a[l+i-1]]=now, mp[a[l+i-1]]=a[r-i+1], ++cnt;
			else if (mp[a[l+i-1]]!=a[r-i+1]) return 0;
		}
		return pw[m-cnt];
	}
	void solve() {
		pw[0]=1;
		for (int i=1; i<=n; ++i) pw[i]=pw[i-1]*m%mod;
		for (int i=1; i<=n; ++i)
			for (int j=i; j<=n; ++j)
				ans=(ans+calc(i, j))%mod;
		cout<<ans<<endl;
	}
}

namespace task{
	ll pw[N], val[N], sum[N], ans;
	int d[N], pre[N], nxt[N], buc[N];
	void solve() {
		pw[0]=1;
		for (int i=1; i<=n; ++i) pw[i]=pw[i-1]*m%mod;
		int lim=n<<1|1;
		for (int i=n; i; --i) a[i<<1]=a[i];
		for (int i=1; i<=lim; ++i) if (i&1) a[i]=m+1;
		for (int i=1; i<=lim; ++i) pre[i]=buc[a[i]], buc[a[i]]=i;
		for (int i=1; i<=m+1; ++i) buc[i]=lim+1;
		for (int i=lim; i; --i) nxt[i]=buc[a[i]], buc[a[i]]=i;
		for (int i=1,mid=0,rs=0,l,r; i<=lim; ++i) {
			// cout<<"i: "<<i<<endl;
			if (i<=rs) {
				d[i]=min(d[mid*2-i], rs-i+1);
				int td=d[mid*2-i];
				ll tval=val[mid*2-i], tsum=sum[mid*2-i];
				l=mid*2-i-td+1, r=mid*2-i+td-1;
				for (; td>d[i]; --td, ++l, --r) if (a[l]!=m+1) {
					// cout<<1<<endl;
					tsum=(tsum-pw[m-tval])%mod;
					if (l==r) --tval;
					else tval=(tval-(nxt[l]>r)-(pre[r]<=l));
				}
				sum[i]=tsum, val[i]=tval;
			}
			// cout<<"sum: "<<sum[i]<<endl;
			// cout<<"val: "<<val[i]<<endl;
			l=i-d[i], r=i+d[i];
			// cout<<"lr: "<<l<<' '<<r<<endl;
			for (; l&&(nxt[l]>r||a[l+r-nxt[l]]==a[r])&&(pre[r]<l||a[l+r-pre[r]]==a[l]); ++d[i], --l, ++r) if (a[l]!=m+1) {
				// cout<<1<<endl;
				if (l==r) val[i]=1, sum[i]=pw[m-val[i]];
				else sum[i]=(sum[i]+pw[m-(val[i]+=(nxt[l]>r)+(pre[r]<=l))])%mod;
			}
			ans=(ans+sum[i])%mod;
			if (r-1>rs) mid=i, rs=r-1;
		}
		// cout<<"i  : "; for (int i=1; i<=lim; ++i) cout<<setw(3)<<i<<' '; cout<<endl;
		// cout<<"a  : "; for (int i=1; i<=lim; ++i) cout<<setw(3)<<a[i]<<' '; cout<<endl;
		// cout<<"d  : "; for (int i=1; i<=lim; ++i) cout<<setw(3)<<d[i]<<' '; cout<<endl;
		// cout<<"val: "; for (int i=1; i<=lim; ++i) cout<<setw(3)<<val[i]<<' '; cout<<endl;
		// cout<<"sum: "; for (int i=1; i<=lim; ++i) cout<<setw(3)<<sum[i]<<' '; cout<<endl;
		cout<<(ans%mod+mod)%mod<<endl;
	}
}

signed main()
{
	freopen("invfunc.in", "r", stdin);
	freopen("invfunc.out", "w", stdout);

	n=read(); m=read();
	for (int i=1; i<=n; ++i) a[i]=read();
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2022-05-16 22:03  Administrator-09  阅读(2)  评论(0编辑  收藏  举报