Identity Theft P
题意是使得对于任意01字符串s1...sn,不存在i,j ,使得si为sj 的前缀。你可以进行的操作使在原来的01字符串后面加0/1,问最少操作次数。
做法:建01字典树,ed[i]去统计有多少字符串以当前结点为结尾,f[i]为增加一个以当前结点为结尾的字符串需要进行多少次操作。
假如当前结点为叶子节点,f[i]=2;如果当前结点只有一个儿子,f[i]=1;如果当前结点有左右儿子lt,rt,则f[i]=min(f[lt],f[rt])+1。
做一遍树形dfs,将不是叶子节点或者数量大于1的字符串下放,优先下放到操作数少的儿子,同时要更新当前的f[i]。
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define fast_io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lt tire[u][0]
#define rt tire[u][1]
#define int long long
const ll INF = 0x3f3f3f3f3f3f;
const int N = 3e5 + 23;
string s[N];
int tot = 1;
int tire[N << 2][3],ed[N<<2],f[N<<2];
void upd(int u) {
f[u] = min(f[lt],f[rt]) + 1;
if((!lt && rt) || (!rt && lt))f[u] = min(f[u],1ll);
if(!lt && ! rt) f[u] = min(f[u],2ll);
}
void ins ( int u) {
if(!lt && !rt) {
lt = ++tot;
rt = ++tot ;
f[lt] = f[rt] = 2;
upd(u);
return ;
}
if(!lt) {
lt = ++tot, f[lt] = 2, upd(u);
return ;
}
if(!rt) {
rt = ++tot, f[rt] = 2, upd(u);
return ;
}
if(f[lt] <= f[rt] )ins(lt);
else ins(rt);
upd(u);
}
ll res =0 ;
void dfs(int u) {
if(lt) dfs(lt) ;
if(rt) dfs(rt);
if(ed[u] && !lt && !rt) --ed[u],f[u] = 2 ;
else upd(u);
while(ed[u]--)res+=f[u],ins(u);
}
void solve() {
f[0]=INF;
int n;
cin >> n;
for (int i = 1; i <= n; i++)cin >> s[i];
for (int i = 1; i <= n; i++) {
int len = s[i].size(); int u = 1;
for(int j = 0; j < len; ++j) {
if(!tire[u][s[i][j] - '0']) tire[u][s[i][j] - '0'] = ++tot;
u = tire[u][s[i][j] - '0'];
}
++ed[u];
}
dfs(1);
cout<<res;
}
signed main() {
fast_io
int t = 1;
// cin >> t;
while (t--)solve();
}
Bessie's Interview S
求最短时间很简单,我们以最短时间为起点,以时间为节点反向建图,如果可以走到a[i]表示i有可能会面试到牛牛。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 10;
int n, k, a[N];
struct ty {
ll x;
int id;
bool operator<(const ty &A) const {
return x > A.x;
}
};
priority_queue<ty> q;
map<ll, int> mp;
int m = 0;
void ins(ll x) {
if (!mp.count(x))mp[x] = ++m;
}
set<int> G[N];
int vis[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= k; i++) {
q.push({a[i], i});
ins(a[i]);
}
int l = k + 1;
while(l<=n){
auto [tmp,id] = q.top();
q.pop();
vector<int>vec;
vec.push_back(id);
while(!q.empty()){
if(q.top().x == tmp){
vec.push_back(q.top().id);
q.pop();
}
else break;
}
for(int i=0 ;i<vec.size();i++){
if(l<=n){
ins(a[l]+tmp);
G[mp[a[l]+tmp]].insert(mp[tmp]);
q.push({a[l++]+ tmp,id});
}
else break;
}
}
cout<<q.top().x<<'\n';
queue<int>Q;
Q.push(mp[q.top().x]);
while(!Q.empty()){
int x = Q.front();
vis[x]=1;
Q.pop();
for(auto to:G[x]){
if(!vis[to]){
Q.push(to);
}
}
}
for(int i=1;i<=k;i++){
cout<<vis[mp[a[i]]];
}
return 0;
}