zoukankan      html  css  js  c++  java
  • 题解CF587C Duff in the Army

    题目:CF587C Duff in the Army

    倍增+归并树。

    用我哥的说法,归并树就是把归并排序的结果记录下来然后乱搞。

    实际上差不多就是这个意思。

    其实就是每次求lca不断向上跳的时候更新答案。

    然后其他都是倍增的板子,很板子。

    其实这题拿到手我犹豫了,不知道写倍增还是写树剖,想想自己倍增要多复习就写了倍增。

    然后惊奇地发现树剖是倍增码量的2~3倍。

    所以考试还是首选倍增+归并树吧。

     1 #include<cstdio>
     2 #include<vector>
     3 #define it register int
     4 #define il inline
     5 using namespace std;
     6 const int N=400005;
     7 int h[N],nxt[N],adj[N],w[N],n,m,Q,fa[N][20],u,v,t,x,d[N];
     8 vector<int> g[N][20],ans;
     9 il void add(){
    10     nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u;
    11 }
    12 il int Min(it p,it q){
    13     return p<q?p:q;
    14 }
    15 il void fr(int &num){
    16     num=0;char c=getchar();int p=1;
    17     while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
    18     while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
    19     num*=p;
    20 }
    21 il vector<int> upd(vector<int>&a,vector<int>&b){
    22     vector<int> c;
    23     c.clear();
    24     it i=0,j=0,sz1=a.size(),sz2=b.size();
    25     while(i<sz1&&j<sz2&&c.size()<10) a[i]<b[j]?c.push_back(a[i++]):c.push_back(b[j++]);
    26     while(i<sz1&&c.size()<10) c.push_back(a[i++]);
    27     while(j<sz2&&c.size()<10) c.push_back(b[j++]);
    28     return c;
    29 }
    30 il void dfs(it x){
    31     d[x]=d[fa[x][0]]+1;
    32     for(it i=h[x];i;i=nxt[i])
    33         if(adj[i]!=fa[x][0]) fa[adj[i]][0]=x,dfs(adj[i]);
    34 } 
    35 il void sp(int &p,int &q){
    36     p+=q,q=p-q,p-=q;
    37 }
    38 il void lca(){
    39     ans.clear();
    40     if(d[u]<d[v]) sp(u,v);
    41     it ds=d[u]-d[v];
    42     for(it i=17;i>=0;--i)
    43         if(ds&(1<<i)) ans=upd(ans,g[u][i]),u=fa[u][i];
    44     if(u==v){ans=upd(ans,g[u][0]);return;}
    45     for(it i=17;i>=0;--i)
    46         if(fa[u][i]!=fa[v][i])
    47             ans=upd(ans,g[u][i]),ans=upd(ans,g[v][i]),u=fa[u][i],v=fa[v][i];
    48     ans=upd(ans,g[v][0]);
    49     if(u!=v) ans=upd(ans,g[u][1]);
    50 }
    51 int main(){
    52     fr(n),fr(m),fr(Q);
    53     for(it i=1;i<n;++i) fr(u),fr(v),add();
    54     for(it i=1;i<=m;++i) fr(x),g[x][0].push_back(i);
    55     dfs(1);
    56     for(it j=1;(1<<j)<=n;++j)
    57         for(it i=1;i<=n;++i)
    58             fa[i][j]=fa[fa[i][j-1]][j-1],g[i][j]=upd(g[i][j-1],g[fa[i][j-1]][j-1]);
    59     while(Q--){
    60         fr(u),fr(v),fr(x),lca();
    61         it sz=Min(x,ans.size());
    62         printf("%d",sz);
    63         for(it j=0;j<sz;++j) printf(" %d",ans[j]);
    64         putchar('
    ');
    65     } 
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    虚拟主机支持apk
    pc显示,手机隐藏
    manjaro个人配置
    docker-compose部署elk
    docker-compose部署zk和kafka
    docker-compose部署redis-cluster
    ActiveMQ与RocketMQ对比
    dropbox离线安装包--需FQ
    C++实现中缀表达式转前、后缀
    运算符优先级
  • 原文地址:https://www.cnblogs.com/Kylin-xy/p/11654662.html
Copyright © 2011-2022 走看看