zoukankan      html  css  js  c++  java
  • CF1555D Say No to Palindromes(线段树)

    CF1555D Say No to Palindromes

    看题目问法是线段树来做的。

    仔细分一下发现,若有一个没有回文子串的串 (s),对于任意 (i),一定有 (s_i eq s_{i-1} eq 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
    ",ans);
    	}
    
    	return 0;
    }
    

    看了一眼官方题解后发现这个题是傻题。

    希望大家学习一下这个思路就行,以官方题解的解法为主。

  • 相关阅读:
    个人兴趣与公司业务的关系
    分析能力的8个等级(转)
    DSL应用的优点
    架构师应具备的概要技能
    Cheetah
    不能运行VS2005的DSL Tool例子
    推荐:原型工具GUI Design Studio
    Viewpoints 1.0 for Visual Studio .NET 2008
    原创故事 - 不死鸡和不死牛的故事
    Antlr构建表达式引擎
  • 原文地址:https://www.cnblogs.com/huayucaiji/p/CF1555D.html
Copyright © 2011-2022 走看看