xsy 2414CF587CDuff in the Army

Posted ez-syh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xsy 2414CF587CDuff in the Army相关的知识,希望对你有一定的参考价值。

Description

【题目描述】:

      最近有一场战争发生,Duff是战争里一名士兵,Malek是她的长官。

      他们的国家——Andarz Gu有n个城市(编号为1到n),总共有n-1条道路,每条道路连接着不同的两个城市,保证两两城市间必定可以通过道路到达。

      Andarz Gu总共有m个人,每个人分别对应着编号1到m,对于第i个人,我们可以知道他还有一个编号ci,表示这个编号为i的人住在编号为ci的城市。注意一个城市里可能有不止一个人,也可能没有人住在这个城市。

      Malek喜欢下达指令,这也是她要问DuffQ(Q个问题,不是DuffQ 个问题)个问题的原因。每一个询问包含三个数u,v,a,Malek要问你的问题就是u到v最短的那条路径上前a小的人的编号分别是什么,如果路径上的人小于a个,就有多少个就输出多少个,如果一个也没有,直接输出0。

      但是Duff现在十分的忙,所以她来向你寻求帮助,请你帮助她回答这q个询问。

【输入描述】:

      第一行输入n,m,q(1<=n,m,q<=10^5)

      接下来n-1行,一行输入两个数v和u,表示城市v和城市u之间有一条双向道路。

      再接下来一行输入m个数,对于ci表示编号为i的人居住的城市。(1<=ci<=n)

      再再接下来q行,每行三个数u,v,a表示一组询问(1<=v,u<=n;1<=a<=10)

【输出描述】:

      对于每组询问,输出它要的答案。

【样例输入】:

5 4 5
1 3
1 2
1 4
4 5
2 1 4 3
4 5 6
1 5 2
5 5 10
2 3 3
5 3 1

【样例输出】:

1 3
2 2 3
0
3 1 2 4
1 2

 
题解思路
由于a<=10,所以只需要在LCA中维护路径中编号最小的十个人即可。
然后就是一个裸的LCA板子了
时间复杂度O(nlogn)
#include<iostream>
#include<cstdio>
using namespace std;
struct data
    int x,y;
t[200001];
struct node
    int p[11],cnt,fa;
f[100001][21],ans;
int n,m,q,x,y,c,k[100001],d[100001],h[100001],fa;
void add(int a,int b,int id)
    t[id].x=b;
    t[id].y=h[a];
    h[a]=id;

node ins(node a,node b)
    node g;
    int l=1,r=1;
    g.cnt=0;
    g.fa=b.fa;
    while(l<=a.cnt||r<=b.cnt)
        if(g.cnt==10)break;
        if(l>a.cnt)
            g.cnt++;
            g.p[g.cnt]=b.p[r];
            r++;
        else if(r>b.cnt)
            g.cnt++;
            g.p[g.cnt]=a.p[l];
            l++;
        else if(a.p[l]<b.p[r])
            g.cnt++;
            g.p[g.cnt]=a.p[l];
            l++;
        else
            g.cnt++;
            g.p[g.cnt]=b.p[r];
            r++;
        
    
    return g;

void dfs(int a)
    for(int i=1;i<=20;i++)f[a][i]=ins(f[a][i-1],f[f[a][i-1].fa][i-1]);
    for(int i=h[a];i;i=t[i].y)
        if(!d[t[i].x])
            d[t[i].x]=d[a]+1;
            f[t[i].x][0].fa=a;
            dfs(t[i].x);
        
    

void lca(int a,int b)
    if(d[a]>d[b])
        for(int i=20;i>=0;i--)
            if(d[f[a][i].fa]>=d[b])
                ans=ins(ans,f[a][i]);
                a=f[a][i].fa;
            
        
    
    if(d[a]<d[b])
        for(int i=20;i>=0;i--)
            if(d[f[b][i].fa]>=d[a])
                ans=ins(ans,f[b][i]);
                b=f[b][i].fa;
            
        
    
    for(int i=20;i>=0;i--)
        if(f[b][i].fa!=f[a][i].fa)
            ans=ins(ans,f[b][i]);
            ans=ins(ans,f[a][i]);
            b=f[b][i].fa;
            a=f[a][i].fa;
        
    
    if(a!=b)
        ans=ins(ans,f[b][0]);
        ans=ins(ans,f[a][0]);
        a=f[a][0].fa;
    
    ans=ins(ans,f[a][0]);

int main()
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<n;i++)
        scanf("%d%d",&x,&y);
        add(x,y,i*2);
        add(y,x,i*2+1);
    
    for(int i=1;i<=m;i++)
        scanf("%d",&x);
        if(f[x][0].cnt<10)
            f[x][0].cnt++;
            f[x][0].p[f[x][0].cnt]=i;
        
    
    d[1]=1;
    dfs(1);
    for(int i=1;i<=q;i++)
        scanf("%d%d%d",&x,&y,&c);
        ans.cnt=0;
        lca(x,y);
        ans.cnt=min(ans.cnt,c);
        printf("%d ",ans.cnt);
        for(int j=1;j<=ans.cnt;j++)printf("%d ",ans.p[j]);
        printf("\n");
    

  

以上是关于xsy 2414CF587CDuff in the Army的主要内容,如果未能解决你的问题,请参考以下文章

XSY2411CF161DDistance in Tree

CF587F Duff is Mad

CF#587Div3

CF809D Hitchhiking in the Baltic States

CF845FGuards In The Storehouse 插头DP

CF587FDuff is Mad AC自动机+分块