hdu 4125 Moles

这几天在做北大出的现场赛题,崩溃。

今天做的11年福州的现场赛题,俩字,呵呵。。。

好几道都是各种算法糅合啊啊啊啊。。。


这个题,比较恶心了,DFS不能用系统栈,得自己写,好吧。不算神马。建二叉查找树不能用普通方法,我用的是map,刚才搜题解好多用线段树的,map足以。

我将数字所在的结点(结构体,左孩子,右孩子的那个结构体)编号存入map,比如你要插入6,之前已经插入了2,3,5,8,那么可以发现,6要么在5的右子树的第一个结点,要么在8的左子树第一个结点(自己证明)。所以,我在map中查找到5,8对应的编号(只会有一种情况满足),然后直接在这个编号的结点上插入。很省时间。


最后DFS后还需要个KMP,我实在无力吐槽了。。。


#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define FORD(i,s,t) for(int i=(s-1); i>=t; i--)
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)

using namespace std;

const int MAX = 600005;
struct NODE{
	int num;
	NODE* left, *right;
};
NODE node[MAX*2];
NODE *root;
int cnt;
int len;
map<int,int> m;
void init() {
	m.clear();
	root = NULL;
	cnt = len = 0;
}
char s[MAX*2];
char pat[7005];
int insert(NODE* &root, int num) {
	if( root == NULL ) {
		node[cnt].num = num;
		node[cnt].left = NULL;
		node[cnt].right = NULL;
		root = &node[cnt];
		return cnt++;
	}
	if( num < root->num )
		return insert(root->left, num);
	else
		return insert(root->right, num);
}

char tochar(int num) {
	return '0' + num%2;
}
void travel(NODE *root) {
	if( root == NULL )
		return ;
	s[len++] = tochar(root->num);
	travel(root->left);
	if( root->left )
		s[len++] = tochar(root->num);
	travel(root->right);
	if( root->right )
		s[len++] = tochar(root->num);
}
int pp[MAX];
bool t[MAX*2];
int stk[MAX*2];
int top;
void travel(int root) {
	memset(t, 0, sizeof(t));
	top = 0;
	stk[top++] = 0;
	while( top > 0 ) {
		int node_num = stk[top-1];
		top--;
		int num = node[node_num].num;
		s[len++] = tochar(num);
		if( t[node_num] )
			continue;
		t[node_num] = true;
		if( node[node_num].right || node[node_num].left )
			stk[top++] = node_num;
		if( node[node_num].right ) {
			int num = node[node_num].right->num;
			stk[top++] = pp[ num ];
		}
		if( node[node_num].right && node[node_num].left )
			stk[top++] = node_num;
		if( node[node_num].left ) {
			int num = node[node_num].left->num;
			stk[top++] = pp[ num ];
		}
	}
}
void kmp2(char *a, int m)
{
    pp[1] = 0;
    int j = 0;
    for(int i = 2; i <= m; ++i)
    {
        while( (j > 0)  && (a[j+1] != a[i]))
            j = pp[j];
        if( a[j+1] == a[i] ) ++j;
        pp[i] = j;
    }
}

int kmp1(char *x, char *a, int n, int m)
{
    int j = 0;
    int cnt = 0;
    for(int i = 1; i <= n; ++i)
    {
        while( (j > 0) &&  (a[j+1] != x[i]))
            j = pp[j];
        if( a[j+1] == x[i] )
            ++j;
        if(j == m){
        	cnt++;
            j = pp[j];
        }
    }
    return cnt;
}

int ans() {
	kmp2(pat-1, strlen(pat));
	return kmp1(s-1, pat-1, strlen(s), strlen(pat)); 
}
int insert_(int node_num, int num) {
	NODE* root = &node[node_num];
	node[cnt].num = num;
	node[cnt].left = NULL;
	node[cnt].right = NULL;
	int pos = cnt++;
	pp[num] = pos;
	m[num] = pos;
	return pos;
}
int main() {
	int ncases, n, num;
	
	map<int,int>::iterator it;
	scanf("%d", &ncases);
	
	for(int ind=1; ind<=ncases; ind++) {
		init();
		scanf("%d", &n);
		FOR(i, 0, n) {
			scanf("%d", &num);
			if( m.size() == 0 ) {
				int pos = insert(root, num);
				m[num] = pos;
				continue;
			}
			it = m.begin();
			if( it->first > num ) {
				int pos = insert_(it->second, num);
				node[it->second].left = &node[pos];
				continue;
			}
			it = m.end();
			it--;
			if( it->first < num ) {
				int pos = insert_(it->second, num);
				node[it->second].right = &node[pos];
				continue;	
			}
			it = m.lower_bound(num);
			int ns = it->second;
			if( node[ns].left == NULL ) {
				int pos = insert_(ns, num);
				node[ns].left = &node[pos];
				continue;
			}
			if( it == m.begin() ) continue;
			it--;
			ns = it->second;
			if( node[ns].right == NULL ) {
				int pos = insert_(ns, num);
				node[ns].right = &node[pos];
				continue;
			}
		}
		scanf("%s", pat);
		travel(0);
		s[len++] = '\0';
		
		printf("Case #%d: %d\n", ind, ans());
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值