1. 程式人生 > 其它 >CF1555D Say No to Palindromes(線段樹)

CF1555D Say No to Palindromes(線段樹)

CF1555D Say No to Palindromes

看題目問法是線段樹來做的。

仔細分一下發現,若有一個沒有迴文子串的串 \(s\),對於任意 \(i\),一定有 \(s_i\neq s_{i-1}\neq s_{i+1}\)。也就是說嗎,這三個字元分別對應 a,b,c。也就是說, \(s\) 的形式只有一下 \(6\) 種:

  • abcabc...
  • bcabca...
  • cabcab...
  • acbacb...
  • cbacba...
  • bacbac...

對於線段樹一個區間,我們維護 \(s_{l,r}\) 對應 \(6\) 種可能修改後的形式修改的字元數量即可。

明顯我們可以通過這 \(6\)

的兩完成 pushup

其他操作和基礎線段樹差不多。

為了寫程式碼方便,你需要對著 \(6\) 種形式合理編號。

//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
using namespace std;

int read() {
	char ch=getchar();
	while(ch<'a'||ch>'c') {
		ch=getchar();
	}
	return (ch-'a'+1)%3;
}

const int MAXN=2e5+10;

int n,m;
int a[MAXN];

struct segment {
	int val[2][3],len;
}s[MAXN<<2];

segment pushup(segment lft,segment rgt) {
	segment ret;
	ret.len=lft.len+rgt.len;
	
	for(int j=0;j<2;j++) {
		for(int i=0;i<3;i++) {
			ret.val[j][i]=lft.val[j][i]+rgt.val[j][(i+lft.len%3)%3];
		}
	}
	return ret;
}

void build(int l,int r,int p) {
	if(l==r) {
		for(int j=0;j<2;j++) {
			for(int i=0;i<3;i++) {
				s[p].val[j][i]=1;
			}
		}
		if(a[l]==1) {
			s[p].val[0][0]=s[p].val[1][0]=0;
		}
		if(a[l]==2) {
			s[p].val[0][1]=s[p].val[1][2]=0;
		}
		if(a[l]==0) {
			s[p].val[0][2]=s[p].val[1][1]=0;
		}
		s[p].len=1;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,p<<1);
	build(mid+1,r,p<<1|1);
	s[p]=pushup(s[p<<1],s[p<<1|1]);
}
segment query(int l,int r,int p,int x,int y) {
	if(r<x||y<l) {
		return s[0];
	}
	if(x<=l&&r<=y) {
		return s[p];
	}
	int mid=(l+r)>>1;
	return pushup(query(l,mid,p<<1,x,y),query(mid+1,r,p<<1|1,x,y));
}

signed main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) {
		a[i]=read();
	}
	build(1,n,1);
	
	while(m--) {
		int l,r;
		scanf("%d%d",&l,&r);
		segment tmp=query(1,n,1,l,r);
		int ans=1e9;
		for(int j=0;j<2;j++) {
			for(int i=0;i<3;i++) {
				ans=min(ans,tmp.val[j][i]);
			}
		}
		printf("%d\n",ans);
	}

	return 0;
}

看了一眼官方題解後發現這個題是傻題。

希望大家學習一下這個思路就行,以官方題解的解法為主。