zoukankan      html  css  js  c++  java
  • 模拟 [D. Colorful Points ]

    模拟 D. Colorful Points

    题目大意:

    给你一个字符串,对于一个字符,如果左右两边的字符和这个不一样,那么就删除这个字符,一次可以删去多个字符,问最少的删除次数,使得不能再删。

    题解:

    这个是一个模拟题,写起来感觉挺恶心的,但是也很考验写题的技巧,用好的技巧写就显得很简洁。

    按照网上的一个思路写的,首先证明一下这个解题思路:

    假设有k个不同的块(每一块都是相同的),那么每次删除 (2*(k-1)) 个数,所以一共遍历 (frac{n}{2*(k-1)}) ,每次遍历的复杂度是 (O(k)) ,所以总的复杂度是 (k*frac{n}{2*(k-1)})

    写法:

    因为最后的形式是 (aaaabbbccababa) ,那么可以等价于 ([4a,3b,2c,1a,1b,1a,1b,1a])

    然后很容易发现,每次操作如果是左右两边的块就 (-1) ,如果是中间的块就 (-2) ,所以每次操作完之后就可以重新合并一次,因为有些块删除之后,两边的块可以连在一起。

    这个合并函数可以记录学习一下,以后碰到类似的可以使用这种方法:

    void cal(){
    	int len = n;
    	n = 0;
    	for(int i=1;i<=len;i++){
    		if(e[i].num>0){
    			if(e[i].val==e[n].val) e[n].num += e[i].num;
    			else e[++n]=e[i];
    		}
    	}
    }
    

    (CODE:)

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define debug(x) cout<<"debug:"<<#x<<" = "<<x<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6+10;
    struct node{
    	int val,num;
    	node(int val=0,int num=0):val(val),num(num){}
    }e[maxn];
    char s[maxn];
    int n;
    void cal(){
    	int len = n;
    	n = 0;
    	for(int i=1;i<=len;i++){
    		if(e[i].num>0){
    			if(e[i].val==e[n].val) e[n].num += e[i].num;
    			else e[++n]=e[i];
    		}
    	}
    }
    
    void solve(){
    	int ans = 0;
    	while(n>1){
    		for(int i=2;i<n;i++) e[i].num -=2;
    		e[1].num--,e[n].num--;
    		ans++;
    		cal();
    	}
    	printf("%d
    ", ans);
    }
    int main(){
    	scanf("%s",s+1);
    	n = strlen(s+1);
    	e[0].val = -1;
    	for(int i=1;i<=n;i++) e[i].val = s[i]-'a',e[i].num = 1;
    	cal();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    div中子div在firefox ie 水平居中对齐
    Access数据库自定义连接字符串(详细有图百度文档)
    ASP页面乱码
    国内开源asp.netCMS汇总
    sql 2005
    卡巴斯基授权key导入方式方法及其导入key基本原理
    关于SqlServer服务无法启动的症状分析和解决方法
    js下流媒体的在线播放
    用JS+vml作三维报表
    了解嵌入式数据库(sqlite,firebird)
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13490849.html
Copyright © 2011-2022 走看看