题解 回文子串
最后一分钟才调出来,然后还不知道自己是在用假的暴力拍假的正解,于是就爆零了
发现 \(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;
}