[Daily] 20200512

C题.[Codeforces 828C] String Reconstructio

题目链接

思路之一:线段树。
用线段树维护区间[l…r]中元素是否已全部染色,对每个ti的所有[xi,j, xi,j+|ti|-1]区间调用线段树的updata染色(走到叶子节点再染色),并打上标记已染色,遇到已染色的就不继续往下走,这样因为每个位置只染色一次,所以时间复杂度为O(LlogL),(L为答案字符串长度上限,|ti|为ti的长度)。同时更新(xi,j+|ti|-1)max得到答案字符串的长度Len,最后输出[1…Len]的染色序列,若某个位置未染色,就输出字符a。
Noting:题目原话为“ It is guaranteed that the sum of lengths of strings ti doesn’t exceed 106, 1 ≤ xi,j ≤ 106, 1 ≤ ki ≤ 106, and the sum of all ki doesn’t exceed 106. ” 意思是答案字符串的最大长度为( xi,jmax+|ti|max-1 ),即2e6,这是一个容易WA/RE的点

这题还有其他更容易写的思路,例如暴力、并查集。

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+7,M=2e6;
char s[N],str[N];
int n,k,Len,f[N];
bool flag[N*4];
inline void push_up(int k){
	flag[k]=flag[k<<1]&&flag[k<<1|1];
}
void updata(int L,int R,int l,int r,int k){
	if(l==r){
		s[l]=str[l-L];
		f[l]=1;
		flag[k]=1;
		return;
	}
	int mid=(l+r)>>1;
	if(L<=mid&&!flag[k<<1])updata(L,R,l,mid,k<<1);
	if(R>mid&&!flag[k<<1|1])updata(L,R,mid+1,r,k<<1|1);
	push_up(k);
}
int main(){
	cin>>n;
	while(n--){
		scanf("%s%d",str,&k);
		int len=strlen(str);
		for(int i=1,x;i<=k;i++){
			scanf("%d",&x);
			updata(x,x+len-1,1,M,1);
			Len=max(Len,x+len-1);
		}
	}
	for(int i=1;i<=Len;i++)
		if(f[i])printf("%c",s[i]);
		else printf("a");
		

猜你喜欢

转载自blog.csdn.net/qq_45530271/article/details/106084319