社区讨论

字典树做法,无需蓝以上证明

P1012[NOIP 1998 提高组] 拼数参与者 26已保存回复 43

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
40 条
当前快照
1 份
快照标识符
@mkp3i21p
此快照首次捕获于
2026/01/22 14:53
4 周前
此快照最后确认于
2026/01/22 20:29
4 周前
查看原帖
CodeCPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e3+5;
int tr[N][10];
pair<int,int> fa[N];
int ed[N];
int ans[N],tot;
int n,cnt=1;
void insert(char* s){
	int l=strlen(s),p=1;
	for(int i=0;i<l;i++){
		int c=s[i]-'0';
		if(!tr[p][c])	tr[p][c]=++cnt,fa[cnt]=make_pair(p,c);
		p=tr[p][c];
	}
	ed[p]++;
	return;
} 
void erase(int p){
	if(ed[p]>1){
		ed[p]--;
		return;
	}
	for(int i=0;i<10;i++)
		if(tr[p][i]){
			ed[p]--;
			return;
		}
	ed[p]--;
	while(!ed[p]&&p!=1){
		int c=0;
		for(int i=0;i<10;i++)
			if(tr[p][i])	c++;
		if(c)	break;
		tr[fa[p].first][fa[p].second]=0;
		p=fa[p].first;
	}
	return;
}
void work(){
	int p=1;
	while(1){
		int F=1;
		while(!ed[p]){
			int f=-1;
			for(int c=9;c>=0;c--){
				if(!tr[p][c])	continue;
				ans[++tot]=c;
				f=c;
				p=tr[p][c];
				F=0;
				break;
			}
//			cout<<p<<'\n';
			if(f==-1){
				break;
			}
		}
		if(F&&p!=1){
			erase(p);
			p=1;
			continue;
		}
		if(F)	break;
//		cout<<p<<'\n';
		int t1=1,t2=p;
		while(1){
//			cout<<t1<<' '<<t2<<'\n';
			int c1=-1,c2=-1;
			for(int c=9;c>=0;c--){
				if(!tr[t1][c])	continue;
				c1=c;
				t1=tr[t1][c];
				break;
			}
			for(int c=9;c>=0;c--){
				if(!tr[t2][c])	continue;
				c2=c;
				t2=tr[t2][c];
				break;
			}
			if(c2==-1){
				erase(t2);
				p=1;
				break;
			}
			if(c1==c2){
				ans[++tot]=c1;
				continue;
			}
			if(c1>c2){
				ans[++tot]=c1;
				erase(p);
				p=t1;
				break;
			}
			if(c2>c1){
				ans[++tot]=c2;
				p=t2;
				break;
			}
		}
	}
	return;
}
char a[20];
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a;
		insert(a);
	}
	work();
	for(int i=1;i<=tot;i++)
		cout<<ans[i];
	return 0;
}
建字典树。复杂度 O(L)O(L)LL 为总长度。
从大到小便利,找到一个 end 后,用两个指针 t1t2,分别从根和当前节点出发,找到第一个不同。
  • t1 指向大于 t2:删除当前节点,使当前指向 t1,继续该过程;
  • t2 指向大于 t1:使当前指向 t2,继续该过程;
  • t2 指向空,删除 t2,使当前节点指向根,继续该过程。
中间 t1t2 相同时直接加到答案里即可。
欢迎 hack。

回复

43 条回复,欢迎继续交流。

正在加载回复...