• P1087 FBI树


    题目链接

    P1087 FBI树

    思路

    思路一

    首先题目中说明了"01"串的长度是(2^n),也就是说这是一棵满二叉树,也就是可以用(tree[i])来表示根(tree[2*i])来表示左孩子,(tree[2*i+1])来表示右孩子

    所以思路就有了直接递归把树的节点弄成"F","B","I".

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn=999999999;
    const int minn=-999999999;
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * f;
    }
    int tree[100010];
    char s[10001];
    int len;
    int build(int l,int r,int num) {
    	if(num==2*len) {
    		return 0;
    	}
    	if(l==r) {
    		if(s[l]=='0') {
    			tree[num]='B';
    			return 'B';
    		} else {
    			tree[num]='I';
    			return 'I';
    		}
    	}
    	char ll=build(l,(l+r)/2,2*num),rr=build((l+r)/2+1,r,2*num+1);
    	if(ll=='F'||rr=='F') {
    		tree[num]='F';
    		return 'F';
    	} else {
    		if(ll != rr) {
    			tree[num]='F';
    			return 'F';
    		} else {
    			if(ll == 'B')	{
    				tree[num] = 'B';
    				return 'B';
    			} else {
    				tree[num] = 'I';
    				return 'I';
    			}
    		}
    	}
    }
    void print(int x) {
    	if(tree[2*x]) print(2*x);
    	if(tree[2*x+1]) print(2*x+1);
    	cout<<char(tree[x]);
    }
    int main() {
    	int x=read();
    	scanf("%s",s+1);
    	len=strlen(s+1);
    	build(1,len,1);
    	print(1);
    	return 0;
    }
    
    

    思路二

    仔细观察会发现只要先递归左边在递归右边最后输出就是树的后序遍历,然后就直接计算字串里的(01)数量就行了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    #define ll long long int
    using namespace std;
    const int maxn=999999999;
    const int minn=-999999999;
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * f;
    }
    int a[10001];
    int n;
    char s[382479];
    void dfs(int l,int r) {
    	if(l<r) {
    		int mid=(r-l)/2;
    		dfs(l,l+mid);
    		dfs(l+mid+1,r);
    	}
    	int sum0=0;
    	int sum1=0;
    	for(int i=l; i<=r; ++i) {
    		if(a[i]==0) sum0++;
    		else sum1++;
    	}
    	if(!sum1) cout<<'B';
    	else if(!sum0) cout<<'I';
    	else  cout<<'F';
    }
    int main() {
    	cin>>n;
    	scanf("%s",s+1);
    	int len=strlen(s+1);
    	for(int i=1; i<=len; ++i) {
    		a[i]=s[i]-'0';
    	}
    	dfs(1,len);
    	return 0;
    }
    

    优化

    利用前缀和来优化计算01的数量的循环
    如果全是(0)(f[r]-f[l-1])相减为(0);
    如果全是(1)(f[r]-f[l-1])相减是(r-l+1);
    反之是(0,1)都有

    
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<map>
    #include<string>
    #include<cstring>
    #define ll long long int
    using namespace std;
    const int maxn=999999999;
    const int minn=-999999999;
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * f;
    }
    int n;
    char s[382479];
    int f[1000101];
    void dfs(int l,int r) {
    	if (l!=r) {
    		int mid=(l+r)/2;
    		dfs(l,mid);
    		dfs(mid+1,r);
    	}
    	if(f[r]-f[l-1]==r-l+1) {
    		cout<<'I';
    	} else if(f[r]-f[l-1]==0) {
    		cout<<"B";
    	} else cout<<"F";
    }
    int main() {
    	cin>>n;
    	scanf("%s",s);
    	n=(1<<n);
    	for(int i=1; i<=n; i++)
    		f[i]=f[i-1]+s[i-1]-'0';
    	dfs(1,n);
    	return 0;
    }
    
    
  • 相关阅读:
    Java连接操作redis
    redis 6.0.x简介和安装
    设计模式之代理模式(proxy)
    设计模式之组合模式(composize)
    Linux Shell脚本调试方法
    linuxcfg.sh
    反向代理和正向代理区别
    WAF与IPS的区别总结
    【LemonCK】jQuery的基本使用
    【LemonCK】CSS盒子塌陷问题
  • 原文地址:https://www.cnblogs.com/pyyyyyy/p/11095551.html
Copyright © 2020-2023  润新知