关闭

[链分治] LOJ #511. 「LibreOJ NOI Round #1」验题

177人阅读 评论(0) 收藏 举报
分类:

直接按照字典序类似逐位确定
先从后往前诸位确定确定答案和当前的LCP
然后在从前往后逐位确定
然后就转化为一个 某些不能选 某些必须选 某些随意 的独立集计数
链分治

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
typedef long double ld;
typedef long long ll;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(ll &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void write(int x){
  if (x>=10) write(x/10);
  putchar('0'+x%10);
}

const int N=1000005;
const int M=30000005;

struct edge{
  int u,v,next;
}G[N<<1];
int head[N],inum;
inline void add(int u,int v,int p){
  G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
#define V G[p].v
int depth[N],fat[N],size[N];
inline void dfs(int u,int fa){
  depth[u]=depth[fa]+1; fat[u]=fa; size[u]=1;
  for (int p=head[u];p;p=G[p].next)
    if (V!=fa)
      dfs(V,u),size[u]+=size[V];
}
int maxd[N],pre[N],clk,back[N],top[N],son[N];
inline void find(int u,int fa,int z){
  pre[u]=++clk; back[clk]=u; top[u]=z; maxd[z]=max(maxd[z],depth[u]);
  int maxv=0; son[u]=0;
  for (int p=head[u];p;p=G[p].next)
    if (V!=fa && size[V]>maxv)
      maxv=size[son[u]=V];
  if (son[u]) find(son[u],u,z);
  for (int p=head[u];p;p=G[p].next)
    if (V!=fa && V!=son[u])
      find(V,u,V);
}

ld K;

int ncnt,rt1[N],rt2[N];
int ls[M],rs[M],ps[M];
ld T[M>>1][2][2],F0[M>>1],F1[M>>1];

inline void upd2(int x){
  F0[x]=min(F0[ls[x]]*F0[rs[x]],K);
  F1[x]=min(F1[ls[x]]*F1[rs[x]],K);
}
vector<int> ch; int pos2[N];
inline void build2(int &x,int l,int r,int p=0){
  x=++ncnt; ps[x]=p;
  if (l==r){
    int u=ch[l-1]; pos2[u]=x;
    F0[x]=min(T[rt1[u]][0][1]+T[rt1[u]][1][0]+T[rt1[u]][0][0]+T[rt1[u]][1][1],K);
    F1[x]=min(T[rt1[u]][0][1]+T[rt1[u]][0][0],K);
    return;
  }
  int mid=(l+r)>>1; build2(ls[x],l,mid,x); build2(rs[x],mid+1,r,x);
  upd2(x);
}
inline void upd1(int x){
  for (int i=0;i<2;i++)
    for (int j=0;j<2;j++)
      T[x][i][j]=min(K,T[ls[x]][i][0]*T[rs[x]][0][j]+T[ls[x]][i][0]*T[rs[x]][1][j]+T[ls[x]][i][1]*T[rs[x]][0][j]);
}
int _pre;
int pos1[N];
inline void build1(int &x,int l,int r,int p=0){
  x=++ncnt; ps[x]=p;
  if (l==r){
    int u=back[_pre+l-1];
    pos1[u]=x;
    T[x][0][0]=F0[rt2[u]]; T[x][1][1]=F1[rt2[u]]; T[x][0][1]=T[x][1][0]=0;
    return;
  }
  int mid=(l+r)>>1; build1(ls[x],l,mid,x); build1(rs[x],mid+1,r,x);
  upd1(x);
}

int n;

inline void Build(){
  static int idx[N],c[N]; F0[0]=F1[0]=1;
  for (int i=1;i<=n;i++) c[depth[i]]++;
  for (int i=1;i<=n;i++) c[i]+=c[i-1];
  for (int i=1;i<=n;i++) idx[c[depth[i]]--]=i;
  for (int i=n;i;i--){
    int u=idx[i];
    for (int p=head[u];p;p=G[p].next)
      if (V!=fat[u] && V!=son[u])
    ch.pb(V);
    if (ch.size()) build2(rt2[u],1,ch.size());
    ch.clear();
    if (top[u]==u){
      _pre=pre[u];
      build1(rt1[u],1,maxd[u]-depth[u]+1);
    }
  }
}

int f[N];

inline void modify(int u,int _f){ // f:0 mustn't 1 must 2 poss
  f[u]=_f; int t=pos1[u],v;

  T[t][0][0]=f[u]==1?0:F0[rt2[u]];
  T[t][1][1]=f[u]==0?0:F1[rt2[u]];
  while (t=ps[t]) upd1(t);

  while (v=fat[top[u]]){
    u=top[u];

    t=pos2[u];
    F0[t]=min(T[rt1[u]][0][1]+T[rt1[u]][1][0]+T[rt1[u]][0][0]+T[rt1[u]][1][1],K);
    F1[t]=min(T[rt1[u]][0][1]+T[rt1[u]][0][0],K);
    while (t=ps[t]) upd2(t);

    t=pos1[v];
    T[t][0][0]=f[v]==1?0:F0[rt2[v]];
    T[t][1][1]=f[v]==0?0:F1[rt2[v]];
    while (t=ps[t]) upd1(t);

    u=v;
  }
}

#define Tot min(T[rt1[1]][0][0]+T[rt1[1]][0][1]+T[rt1[1]][1][0]+T[rt1[1]][1][1],K)

int I[N];

int main(){
  ll k; static int iu[N],iv[N];
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(n); read(k); K=k+5;
  for (int i=1;i<n;i++) read(iu[i]),iu[i]++;
  for (int i=1;i<n;i++) read(iv[i]),iv[i]++,add(iu[i],iv[i],++inum),add(iv[i],iu[i],++inum);
  read(*I); for (int i=1;i<=*I;i++) read(I[i]),I[i]++; sort(I+1,I+*I+1);
  dfs(1,0); find(1,0,1);
  Build();
  for (int i=1;i<=n;i++) f[i]=2;
  for (int i=1;i<=*I;i++){
    for (int j=(i==1?0:I[i-1])+1;j<I[i];j++)
      modify(j,0);
    modify(I[i],1);
  }
  int c=0;
  for (int i=*I;i;i--){
    if (Tot-1<k)
      k-=Tot-1;
    else
      break;
    modify(I[i],0); c++;
    for (int j=I[i]+1;j<=(i==*I?n:I[i+1]);j++)
      modify(j,2);
  }
  *I-=c;
  if (Tot-1<k) return printf(""),0;
  for (int i=1;i<=n;i++){
    if (f[i]!=2) continue;
    modify(i,1);
    if (Tot<k){
      k-=Tot;
      modify(i,0);
    }else
      I[++*I]=i,k--;
    if (!k) break;
  }
  for (int i=1;i<=*I;i++)
    write(I[i]-1),putchar(' ');
  return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:308753次
    • 积分:12395
    • 等级:
    • 排名:第1311名
    • 原创:969篇
    • 转载:3篇
    • 译文:0篇
    • 评论:54条
    最新评论