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

来源:互联网 发布:数据预测模型有哪些 编辑:程序博客网 时间:2024/05/16 19:46

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

#include<cstdio>#include<cstdlib>#include<algorithm>#include<vector>#define pb push_backusing 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].vint 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