Codeforces 828C
题意:给出n个字符串s,对每一个字符串可以给出m个位置ki,表示可以把字符串填到ki~ki+len(s)上,保证不会冲突,求最后符合条件的字典序最小字符串。
尝试用线段树写了一下
设置一个tag标记,如果区间整个都做过修改,tag为真,下次碰到这个区间后就直接跳过了
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 2e6 + 10;
char ans[maxn];
struct Tree{
int l, r;
bool tag;
};
Tree t[maxn<<2];
void build(int l, int r, int root)
{
t[root].l = l, t[root].r = r;
t[root].tag = false;
if(t[root].l != t[root].r){
int mid = (t[root].l + t[root].r) >> 1;
build(l, mid, root << 1);
build(mid + 1, r, root << 1 | 1);
}
}
void update(int l, int r, string &s, int root)
{
if(t[root].tag) return;
else if((t[root].l == t[root].r)){
ans[t[root].l] = s[t[root].l - l];
t[root].tag = true;
return;
}
else{
int mid = (t[root].l + t[root].r) >> 1;
if(r <= mid) update(l, r, s, root << 1);
else if(l > mid) update(l, r, s, root << 1 | 1);
else{
update(l, r, s, root << 1);
update(l, r, s, root << 1 | 1);
}
if(t[root << 1].tag && t[root << 1 | 1].tag)
t[root].tag = true;
}
}
string s[maxn];
vector<int> a[maxn];
int main()
{
int n; scanf("%d", &n);
for(int i = 0; i < n; i++) a[i].clear();
int Max = 0;
for(int i = 0; i < n; i++){
cin>>s[i];
int m; scanf("%d", &m);
int len = s[i].length();
for(int j = 0; j < m; j++){
int temp; scanf("%d",&temp);
a[i].push_back(temp);
Max = max(Max, len + temp - 1);
}
}
for(int i = 0; i <= Max+10; i++)
ans[i] = 'a';
build(0, Max, 1);
for(int i = 0; i < n; i++){
int len = s[i].length();
for(int j = 0; j < a[i].size(); j++){
update(a[i][j]-1, a[i][j]+len-2, s[i], 1);
}
}
for(int i = 0; i < Max; i++)
printf("%c",ans[i]);
return 0;
}