题解 路过中丹

传送门

首先手玩发现性质:
假如一个串存在两个相等的字符中间只隔着一个字符,那么这个串就一定“配得上丹”
否则是否“配得上丹”等价于是否存在偶回文覆盖(使用若干偶回文串覆盖所有字符)

前一个很好处理,考虑后一个怎么维护
一个方法是离线后扫描线
对于一个右端点 \(r\),若令线段树下标 \(i\) 处存能覆盖 \(i\) 的偶回文串左端点最大值
那么一个子区间 \([l, r]\) 合法的条件是这个区间的最小值 \(\geqslant l\)
维护的话需要知道以其为右端点的偶回文串左端点最大值
可以 manacher 求出来

  • 貌似所有「覆盖范围随询问区间动态变化」的覆盖问题都可以离线下来扫描线处理?
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
#define fir first
#define sec second
#define pb push_back
#define ull unsigned long long
//#define int long long

int n, m;
char s[N];

namespace force{
	int l, r;
	bool vis[N];
	string s2;
	void dfs(int u, string s2, vector<int> pos, int t) {
		if (s2.size()>4*(r-l+1)) return ;
		s2.pb(s[u]); pos.pb(u);
		if (u!=t) {
			string tem=s2;
			reverse(tem.begin(), tem.end());
			if (tem==s2) for (auto it:pos) vis[it]=1;
		}
		if (u-1>=l) dfs(u-1, s2, pos, t);
		if (u+1<=r) dfs(u+1, s2, pos, t);
	}
	void solve() {
		for (int i=1; i<=m; ++i) {
			// cerr<<"i: "<<i<<endl;
			scanf("%d%d", &l, &r);
			for (int j=l; j<=r; ++j) vis[j]=0;
			for (int j=l; j<=r; ++j) dfs(j, string(), vector<int>(), j);
			for (int j=l; j<=r; ++j) if (!vis[j]) {printf("0"); goto jump;}
			printf("1");
			jump: ;
		}
		printf("\n");
	}
}

namespace task1{
	bool vis[N];
	void solve() {
		for (int i=1,l,r; i<=m; ++i) {
			scanf("%d%d", &l, &r);
			for (int j=l+1; j<r; ++j) if (s[j-1]==s[j+1]) {printf("1"); goto jump;}
			for (int j=l; j<=r; ++j) vis[j]=0;
			for (int j=l; j<=r; ++j) {
				for (int k=0; k<=min(j-l, r-j-1); ++k) {
					if (s[j-k]==s[j+1+k]) vis[j-k]=vis[j+1+k]=1;
					else break;
				}
			}
			for (int j=l; j<=r; ++j) if (!vis[j]) {printf("0"); goto jump;}
			printf("1");
			jump: ;
		}
		printf("\n");
	}
}

namespace task2{
	bool vis[N];
	ull h[N], rh[N], p[N];
	int bit[N];
	const ull base=13131;
	inline ull hashing(int l, int r) {return h[r]-h[l-1]*p[r-l+1];}
	inline ull rhash(int l, int r) {return rh[l]-rh[r+1]*p[r-l+1];}
	inline void upd(int i, int dat) {for (; i<=n; i+=i&-i) bit[i]+=dat;}
	inline int query(int i) {int ans=0; for (; i; i-=i&-i) ans+=bit[i]; return ans;}
	void solve() {
		p[0]=1;
		for (int i=1; i<=n; ++i) p[i]=p[i-1]*base;
		for (int i=1; i<=n; ++i) h[i]=h[i-1]*base+s[i];
		for (int i=n; i; --i) rh[i]=rh[i+1]*base+s[i];
		for (int i=1,l,r; i<=m; ++i) {
			scanf("%d%d", &l, &r);
			for (int j=l+1; j<r; ++j) if (s[j-1]==s[j+1]) {printf("1"); goto jump;}
			for (int j=0; j<=n; ++j) bit[j]=0;
			for (int j=l; j<r; ++j) if (s[j]==s[j+1]) {
				// cout<<"j: "<<j<<endl;
				int ql=1, qr=min(j-l+1, r-j), mid;
				// cout<<"lr: "<<ql<<' '<<qr<<endl;
				while (ql<=qr) {
					mid=(ql+qr)>>1;
					// cout<<"mid: "<<mid<<' '<<hashing(j-mid+1, j)<<' '<<rhash(j+1, j+mid)<<endl;
					if (hashing(j-mid+1, j)==rhash(j+1, j+mid)) ql=mid+1;
					else qr=mid-1;
				}
				int len=ql-1;
				// cout<<"len: "<<len<<endl;
				assert(j-len+1>=l && j+len<=r);
				upd(j-len+1, 1); upd(j+len+1, -1);
			}
			for (int j=l; j<=r; ++j) if (query(j)==0) {printf("0"); goto jump;}
			printf("1");
			jump: ;
		}
		printf("\n");
	}
}

namespace task{
	char t[N<<1], *c;
	bool ans[N];
	pair<int, int> sta[N];
	vector<pair<int, int>> que[N];
	int tl[N<<2], tr[N<<2], mn[N<<2], tag[N<<2];
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	#define mn(p) mn[p]
	#define tag(p) tag[p]
	#define pushup(p) mn(p)=min(mn(p<<1), mn(p<<1|1))
	int bit[N], ql[N], qr[N], d[N<<1], lst[N], top;
	inline void upd(int i, int dat) {for (; i<=n; i+=i&-i) bit[i]+=dat;}
	inline int query(int i) {int ans=0; for (; i; i-=i&-i) ans+=bit[i]; return ans;}
	void manacher() {
		int n=0; c=s+1;
		t[++n]='$'; t[++n]='#';
		while (*c) t[++n]=*(c++), t[++n]='#';
		for (int i=1,mid=0,r=0; i<=n; ++i) {
			if (i<=r) d[i]=min(r-i+1, d[mid*2-i]);
			while (t[i-d[i]]==t[i+d[i]]) ++d[i];
			if (i+d[i]-1>r) r=i+d[i]-1, mid=i;
			// cout<<sta[top].fir+sta[top].sec-1<<endl;
			while (top && sta[top].fir+sta[top].sec-1<i) --top; //, cout<<"pop1"<<endl;
			// cout<<"at "<<i<<": "; for (int i=1; i<=top; ++i) cout<<sta[i].fir<<','<<sta[i].sec<<' '; cout<<endl;
			if (i&1) {
				if (top) lst[i>>1]=(sta[top].fir*2-i)>>1;
				// cout<<"pos1: "<<i<<endl;
			}
			else if (d[i]) {
				while (top && sta[top].fir+sta[top].sec-1 <= i+d[i]-1) --top; //, cout<<"pop2"<<endl;
				sta[++top]={i, d[i]};
			}
		}
		// cout<<"lst: "; for (int i=1; i<=n; ++i) cout<<lst[i]<<' '; cout<<endl;
		// cout<<"d: "; for (int i=1; i<=n*2; ++i) cout<<d[i]<<' '; cout<<endl;
		// cout<<"t: "; for (int i=1; i<=n*2; ++i) cout<<t[i]<<' '; cout<<endl;
	}
	void spread(int p) {
		if (!tag(p)) return ;
		mn(p<<1)=max(mn(p<<1), tag(p)); tag(p<<1)=max(tag(p<<1), tag(p));
		mn(p<<1|1)=max(mn(p<<1|1), tag(p)); tag(p<<1|1)=max(tag(p<<1|1), tag(p));
		tag(p)=0;
	}
	void build(int p, int l, int r) {
		tl(p)=l; tr(p)=r;
		if (l==r) return ;
		int mid=(l+r)>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
	}
	void upd(int p, int l, int r, int val) {
		if (l<=tl(p)&&r>=tr(p)) {mn(p)=max(mn(p), val); tag(p)=max(tag(p), val); return ;}
		spread(p);
		int mid=(tl(p)+tr(p))>>1;
		if (l<=mid) upd(p<<1, l, r, val);
		if (r>mid) upd(p<<1|1, l, r, val);
		pushup(p);
	}
	int query(int p, int l, int r) {
		if (l<=tl(p)&&r>=tr(p)) return mn(p);
		spread(p);
		int mid=(tl(p)+tr(p))>>1, ans=INF;
		if (l<=mid) ans=min(ans, query(p<<1, l, r));
		if (r>mid) ans=min(ans, query(p<<1|1, l, r));
		return ans;
	}
	void solve() {
		manacher(); build(1, 1, n);
		for (int i=2; i<n; ++i) if (s[i-1]==s[i+1]) upd(i, 1);
		for (int i=1; i<=m; ++i) scanf("%d%d", &ql[i], &qr[i]), que[qr[i]].pb({ql[i], i});
		for (int i=1; i<=n; ++i) {
			// cout<<"i: "<<i<<endl;
			if (lst[i]) upd(1, lst[i], i, lst[i]);
			for (auto it:que[i]) ans[it.sec]=query(1, it.fir, i)>=it.fir;
		}
		for (int i=1,l,r; i<=m; ++i) {
			l=ql[i], r=qr[i];
			if (l==r) printf("0");
			else if (query(r-1)-query(l)!=0) printf("1");
			else if (ans[i]) printf("1");
			else printf("0");
		}
		printf("\n");
	}
}

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

	scanf("%d%s%d", &n, s+1, &m);
	// force::solve();
	// task1::solve();
	// task2::solve();
	task::solve();

	return 0;
}
posted @ 2022-01-24 10:37  Administrator-09  阅读(2)  评论(0编辑  收藏  举报