题解 回文子串

传送门

最后一分钟才调出来,然后还不知道自己是在用假的暴力拍假的正解,于是就爆零了

发现 \(k\) 很小,所以每次修改只需要枚举左右加起来一共 \(8k\) 长的区间
剩下的区间的值除了特殊字符都是一样的
特殊字符的值是其他字符的值和 \(\frac{k}{2}\) 取min
分块维护序列可以做到 \(O(n\sqrt n+nklogn)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long

int n, k, q;
int bkp[N], d[N], t_ans[N], bel[N], ls[N], len;
char s[N], c[N], t[N], tem[N];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define sum(p) sum[p]
#define tag(p) tag[p]
#define len1(p) len1[p]
#define len2(p) len2[p]
namespace seg{
	char tag[N];
	void spread(int sid) {
		if (tag[sid]) {
			for (int i=ls[sid]; bel[i]==sid; ++i) if (s[i]!='#'&&s[i]!='$') s[i]=tag[sid];
			tag[sid]=0;
		}
	}
	void upd(int l, int r, int c) {
		int sid=bel[l], eid=bel[r];
		if (sid==eid) {
			spread(sid);
			for (int i=l; i<=r; ++i) if (s[i]!='#'&&s[i]!='$') s[i]=c;
			return ;
		}
		spread(sid); spread(eid);
		for (int i=l; bel[i]==sid; ++i) if (s[i]!='#'&&s[i]!='$') s[i]=c;
		for (int i=r; bel[i]==eid; --i) if (s[i]!='#'&&s[i]!='$') s[i]=c;
		for (int i=sid+1; i<eid; ++i) tag[i]=c;
	}
	inline char qchr(int i) {if (s[i]=='#'||s[i]=='$') return s[i]; return tag[bel[i]]?tag[bel[i]]:s[i];}
}
// namespace sega{
// 	int ans[N];
// 	void init() {
// 		for (int i=1,mid=0,r=0; i<=n; ++i) {
// 			if (i<=r) d[i]=min(d[mid*2-i], r-i+1);
// 			while (s[i-d[i]]==s[i+d[i]]) ++d[i];
// 			if (i+d[i]-1>r) r=i+d[i]-1, mid=i;
// 			if (s[i]=='#') ans[i]=min(2*(d[i]/2), k)/2;
// 			else ans[i]=(min(d[i]-1, k)+1)/2;
// 		}
// 	}
// 	void show() {for (int i=1; i<=n; ++i) cout<<setw(2)<<ans[i]<<' '; cout<<"(show)"<<endl;}
// 	void upd(int p, int pos, int val) {ans[pos]=s[pos]=='#'?min(val, k/2):val;}
// 	void upd(int p, int l, int r, int val) {for (int i=l; i<=r; ++i) ans[i]=s[i]=='#'?min(val, k/2):val;}
// 	int query(int p, int l, int r) {int tem=0; for (int i=l; i<=r; ++i) tem+=ans[i]; return tem;}
// }
namespace sega{
	int tl[N<<2], tr[N<<2], ans[N], sum[N<<2], tag[N<<2], len1[N<<2], len2[N<<2];
	#define pushup(p) sum(p)=sum(p<<1)+sum(p<<1|1)
	void build(int p, int l, int r) {
		tl(p)=l; tr(p)=r;
		if (l==r) {if (s[l]=='#') ++len2(p); else ++len1(p); sum(p)=ans[l]; return ;}
		int mid=(l+r)>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
		len1(p)=len1(p<<1)+len1(p<<1|1);
		len2(p)=len2(p<<1)+len2(p<<1|1);
		pushup(p);
	}
	void init() {
		for (int i=1,mid=0,r=0; i<=n; ++i) {
			if (i<=r) d[i]=min(d[mid*2-i], r-i+1);
			while (s[i-d[i]]==s[i+d[i]]) ++d[i];
			if (i+d[i]-1>r) r=i+d[i]-1, mid=i;
			if (s[i]=='#') ans[i]=min(2*(d[i]/2), k)/2;
			else ans[i]=(min(d[i]-1, k)+1)/2;
		}
		build(1, 1, n);
	}
	void spread(int p) {
		if (!tag(p)) return ;
		sum(p<<1)=1ll*len1(p<<1)*tag(p)+1ll*len2(p<<1)*min(tag(p), k/2); tag(p<<1)=tag(p);
		sum(p<<1|1)=1ll*len1(p<<1|1)*tag(p)+1ll*len2(p<<1|1)*min(tag(p), k/2); tag(p<<1|1)=tag(p);
		tag(p)=0;
	}
	void upd(int p, int l, int r, int val) {
		if (l<=tl(p)&&r>=tr(p)) {sum(p)=1ll*len1(p)*val+1ll*len2(p)*min(val, k/2); 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>r) return 0;
		if (l<=tl(p)&&r>=tr(p)) return sum(p);
		spread(p);
		int mid=(tl(p)+tr(p))>>1, ans=0;
		if (l<=mid) ans+=query(p<<1, l, r);
		if (r>mid) ans+=query(p<<1|1, l, r);
		return ans;
	}
}
void calc(int n) {
	// cout<<t+1<<endl;
	for (int i=1; i<=n; ++i) d[i]=0;
	for (int i=1,mid=0,r=0; i<=n; ++i) {
		if (i<=r) d[i]=min(d[mid*2-i], r-i+1);
		while (tem[i-d[i]]==tem[i+d[i]]) ++d[i];
		if (i+d[i]-1>r) r=i+d[i]-1, mid=i;
		if (tem[i]=='#') t_ans[i]=min(2*(d[i]/2), k)/2;
		else t_ans[i]=(min(d[i]-1, k)+1)/2;
	}
	// for (int i=1; i<=n; ++i) cout<<setw(2)<<d[i]<<' '; cout<<"(d)"<<endl;
	// for (int i=1; i<=n; ++i) cout<<setw(2)<<t_ans[i]<<' '; cout<<"(t_ans)"<<endl;
}
void solve() {
	// for (int i=1; i<=n; ++i) cout<<setw(2)<<s[i]<<' '; cout<<endl;
	// for (int i=1; i<=n; ++i) cout<<setw(2)<<i<<' '; cout<<endl;
	// sega::show();
	for (int i=1,op,l,r; i<=q; ++i) {
		scanf("%d", &op);
		if (op&1) {
			// cout<<"op=1"<<endl;
			scanf("%d%d%s", &l, &r, c);
			l=l<<1|1, r=r<<1|1;
			// for (int j=l; j<=r; j+=2) s[j]=*c;
			seg::upd(l, r, *c);
			int pos=1, beg=2, end=0;
			tem[1]='$';
			for (int j=max(l-4*k-1, 2); j<=min(l+4*k+1, n); ++j) {
				tem[++pos]=seg::qchr(j);
				bkp[pos]=j;
				if (j==l-k*2) beg=pos;
				if (j==l+k*2) end=pos;
			}
			// cout<<"pos: "<<pos<<endl;
			// cout<<"tem: "<<endl;
			// for (int j=1; j<=pos; ++j) cout<<setw(2)<<tem[j]<<' '; cout<<endl;
			if (!end) end=pos;
			// cout<<"beg: "<<beg<<' '<<end<<endl;
			calc(pos);
			for (int j=beg; j<=end; ++j) sega::upd(1, bkp[j], bkp[j], t_ans[j]);
			// sega::show();

			pos=1, beg=2, end=0;
			tem[1]='$';
			for (int j=max(r-4*k-1, 2); j<=min(r+4*k+1, n); ++j) {
				tem[++pos]=seg::qchr(j);
				bkp[pos]=j;
				if (j==r-k*2) beg=pos;
				if (j==r+k*2) end=pos;
			}
			// cout<<"pos: "<<pos<<endl;
			// cout<<"tem: "<<endl;
			// for (int j=1; j<=pos; ++j) cout<<setw(2)<<tem[j]<<' '; cout<<endl;
			if (!end) end=pos;
			// cout<<"beg: "<<beg<<' '<<end<<endl;
			calc(pos);
			for (int j=beg; j<=end; ++j) sega::upd(1, bkp[j], bkp[j], t_ans[j]);
			// sega::show();

			// cout<<"mid: "<<l+k*2+1<<' '<<r-k*2-1<<endl;
			if (l+k*2+1<=r-k*2-1) sega::upd(1, l+k*2+1, r-k*2-1, (k+1)/2);
			// sega::show();
		}
		else {
			// cout<<"op=2"<<endl;
			// sega::show();
			// for (int i=1; i<=n; ++i) cout<<setw(2)<<seg::qchr(i)<<' '; cout<<endl;
			scanf("%d%d", &l, &r);
			l=l<<1|1, r=r<<1|1;
			int ans=0;
			if (r-l<=k*4) {
				for (int i=l; i<=r; ++i) ans+=min(sega::query(1, i, i), (seg::qchr(i)=='#' ? min((i-l+1)/2, (r-i+1)/2) : min((i-l+2)/2, (r-i+2)/2))); //, cout<<"i: "<<i<<' '<<sega::qval(i)<<' '<<min((i-l+1)/2, (r-i+1)/2)<<endl;
				// printf("way1: %d\n", ans);
				printf("%d\n", ans);
			}
			else {
				for (int i=l; i<=l+k*2; ++i) ans+=min(sega::query(1, i, i), (seg::qchr(i)=='#' ? min((i-l+1)/2, (r-i+1)/2) : min((i-l+2)/2, (r-i+2)/2)));
				for (int i=r-k*2; i<=r; ++i) ans+=min(sega::query(1, i, i), (seg::qchr(i)=='#' ? min((i-l+1)/2, (r-i+1)/2) : min((i-l+2)/2, (r-i+2)/2)));
				ans+=sega::query(1, l+k*2+1, r-k*2-1);
				// printf("way2: %d\n", ans);
				printf("%d\n", ans);
			}
		}
	}
}

signed main()
{
	scanf("%s%d%d", t, &k, &q);
	memset(ls, 127, sizeof(ls));
	char *c=t;
	s[++n]='$'; s[++n]='#';
	while (*c) s[++n]=*(c++), s[++n]='#';
	len=sqrt(n);
	for (int i=1; i<=n; ++i) bel[i]=(i-1)/len+1, ls[bel[i]]=min(ls[bel[i]], i);
	sega::init();
	solve();
	
	return 0;
}
posted @ 2021-12-12 19:07  Administrator-09  阅读(4)  评论(0编辑  收藏  举报