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

    CF587C Duff in the Army

    洛谷传送门

    题目描述

    Recently Duff has been a soldier in the army. Malek is her commander.

    Their country, Andarz Gu has nn cities (numbered from 11 to nn ) and n-1n−1 bidirectional roads. Each road connects two different cities. There exist a unique path between any two cities.

    There are also mm people living in Andarz Gu (numbered from 11 to mm ). Each person has and ID number. ID number of i-thit**h person is ii and he/she lives in city number c_{i}c**i . Note that there may be more than one person in a city, also there may be no people living in the city.

    imgMalek loves to order. That's why he asks Duff to answer to qq queries. In each query, he gives her numbers v,uv,u and aa .

    To answer a query:

    Assume there are xx people living in the cities lying on the path from city vv to city uu . Assume these people's IDs are p_{1},p_{2},...,p_{x}p1,p2,...,p**x in increasing order.

    If k=min(x,a)k=min(x,a) , then Duff should tell Malek numbers k,p_{1},p_{2},...,p_{k}k,p1,p2,...,p**k in this order. In the other words, Malek wants to know aa minimums on that path (or less, if there are less than aa people).

    Duff is very busy at the moment, so she asked you to help her and answer the queries.

    输入格式

    The first line of input contains three integers, n,mn,m and qq ( 1<=n,m,q<=10^{5}1<=n,m,q<=105 ).

    The next n-1n−1 lines contain the roads. Each line contains two integers vv and uu , endpoints of a road ( 1<=v,u<=n1<=v,u<=n , v≠uv�=u ).

    Next line contains mm integers c_{1},c_{2},...,c_{m}c1,c2,...,c**m separated by spaces ( 1<=c_{i}<=n1<=c**i<=n for each 1<=i<=m1<=i<=m ).

    Next qq lines contain the queries. Each of them contains three integers, v,uv,u and aa ( 1<=v,u<=n1<=v,u<=n and 1<=a<=101<=a<=10 ).

    输出格式

    For each query, print numbers k,p_{1},p_{2},...,p_{k}k,p1,p2,...,p**k separated by spaces in one line.

    题意翻译

    题目描述

    Duff是一个军队中的一名士兵。Malek是的上司。

    他们在一个名为Andarz Gu的国家里,这个国家有 nn 个城市,分别编号 1-n1−n 。有 n-1n−1 条双向通行的道路联通整个国家。

    一共有 mm 个人居住在这个国家中的一些城市里,每一个人有他的身份号(第 ii 个人的身份号是 ii )。注意,有可能有多个人居住在同一个城市,也有可能有些城市无人居住。

    Malek喜欢对别人下命令,所以他让Duff回答他的q个提问,每一个提问包含三个数 vv , uu 和 aa

    为了回答一个提问:
    设想一共有 xx 个人居住在从城市 uu 到城市 vv (包含)的路径上,他们的身份号从小到大排序后分别是 p_1,p_2,...,p_xp1​,p2​,...,p**x​ 。如果设 k=min(x,a)k=min(x,a) ,那么Duff应该按顺序告诉Malek k,p_1,p_2,...,p_kk,p1​,p2​,...,p**k​ 。从另一种说法来说,Malek想要知道在路径上身份编号前 aa 小的人(或者更少,如果这条路上总共居住的人少于 aa 个)。

    Duff现在非常忙碌,所以她让你来帮助她回答Malek的提问。

    输入输出格式

    输入格式

    输入的第一行包括3个整数, nn , mm 和 qq 。(1<=n,m,q<=10^51<=n,m,q<=105 )

    接下来的 n-1n−1 行描述了连通城市的道路。每一行包括两个整数 uu 和 vv ,表示从城市 uu 到城市 vv 有一条双向道路。(1<=u,v<=n , u≠v1<=u,v<=n,u�=v

    接下来的一行包括 mm 个正整数 c_1,c_2,...,c_mc1,c2,...,c**m , c_ic**i 表示编号为 ii 的人居住在城市 c_ic**i 里。(1<=c_i<=n1<=c**i<=n ,对于每一个 ii 有 1<=i<=m1<=i<=m

    接下来的 qq 行描述了Malek的提问。每一行包括三个正整数 uu , vv 和 aa (1<=v,u<=n1<=v,u<=n ,1<=a<=101<=a<=10 ,含义见题面)

    输出格式

    对于每一次提问,输出一行,包括 k,p_1,p_2,...,p_kk,p1,p2,...,p**k (含义见题面)。

    感谢@星烁晶熠辉 提供的翻译


    题解:

    还是数据范围能给出更多的提示。

    看到这个(ale 10),还要输出前k小的都是谁,那么就直接考虑暴力维护前10即可。

    然后是路径统计。考虑树上倍增和树链剖分。但是对比一下,倍增对树链的维护更容易理解和好码一些。所以采用了vector维护前十集合+倍增。

    唯一需要注意的点就是vector的合并问题。可以考虑类似归并排序的做法,把两个vector合并进一个vector里。

    剩下的就是裸的树上倍增了。

    代码:

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+10;
    int n,m,q;
    int tot,to[maxn<<1],nxt[maxn<<1],head[maxn];
    int fa[maxn][20],deep[maxn];
    vector<int> c[maxn];
    vector<int> set[maxn][20];
    vector<int> ans;
    void add(int x,int y)
    {
    	to[++tot]=y;
    	nxt[tot]=head[x];
    	head[x]=tot;
    }
    vector<int> merge(vector<int> a,vector<int> b)
    {
    	int i=0,j=0;
    	vector<int> ret;
    	ret.clear();
    	while(i<a.size()&&j<b.size()&&ret.size()<10)
    	{
    		if(a[i]<b[j])
    			ret.push_back(a[i++]);
    		else
    			ret.push_back(b[j++]);
    	}
    	while(i<a.size()&&ret.size()<10)
    		ret.push_back(a[i++]);
    	while(j<b.size()&&ret.size()<10)
    		ret.push_back(b[j++]);
    	return ret;
    }
    void dfs(int x,int f)
    {
    	deep[x]=deep[f]+1;
    	fa[x][0]=f;
    	set[x][0]=c[x];
    	for(int i=1;i<=19;i++)
    	{
    		fa[x][i]=fa[fa[x][i-1]][i-1];
    		set[x][i]=merge(set[x][i-1],set[fa[x][i-1]][i-1]);
    	}
    	for(int i=head[x];i;i=nxt[i])
    	{
    		int y=to[i];
    		if(y==f)
    			continue;
    		dfs(y,x);
    	}
    }
    vector<int> solve(int x,int y)
    {
    	vector<int> ret;
    	ret.clear();
    	if(deep[x]<deep[y])
    		swap(x,y);
    	for(int i=19;i>=0;i--)
    		if(deep[fa[x][i]]>=deep[y])
    		{
    			ret=merge(ret,set[x][i]);
    			x=fa[x][i];
    		}
    	if(x==y)
    	{
    		ret=merge(ret,set[x][0]);
    		return ret;
    	}
    	for(int i=19;i>=0;i--)
    		if(fa[x][i]!=fa[y][i])
    		{
    			ret=merge(ret,set[x][i]);
    			ret=merge(ret,set[y][i]);
    			x=fa[x][i];
    			y=fa[y][i];
    		}
    	ret=merge(ret,set[x][0]);
    	if(x!=y)
    		ret=merge(ret,set[y][1]);
    	return ret;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<n;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	for(int i=1;i<=m;i++)
    	{
    		int x;
    		scanf("%d",&x);
    		c[x].push_back(i);
    	}
    	dfs(1,0);
    	while(q--)
    	{
    		int x,y,a;
    		scanf("%d%d%d",&x,&y,&a);
    		ans.clear();
    		ans=solve(x,y);
    		int sz=ans.size();
    		int k=min(sz,a);
    		printf("%d ",k);
    		for(int i=0;i<k;i++)
    			printf("%d ",ans[i]);
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何申请iOS开发者证书/发布app到手机
    STL
    TCP/IP编程
    STL
    STL
    Python网络爬虫
    Python网络爬虫
    Python网络爬虫
    Python编程-基础知识-python项目包和文件的管理以及如何引用相对路径的包和模块
    带你认识HL7和CDA
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13867647.html
Copyright © 2011-2022 走看看