[codeforces]Round #537 (Div. 2)E. Tree

题解:  q次查询每次查询k个点  k的总和不超过1e5  那就->虚树  这个题分为两部分  前面先对每次查询的点建虚树 其次计数  对于新树上的每个关键点(查询点)  他能影响的m的范围 必然大于以r为根的祖先节点的个数 然后我们单独考虑每个节点的贡献为 当前集合个数减去其祖先节点的个数  然后我们考虑把每个点按照dfs序的下标考虑贡献  转移分为两部分

      1.当前元素加入直接构成一个新集合

      2,当前元素加入可以加入到  m(当前集合个数)-祖先节点个数

#include <bits/stdc++.h>
#define ll long long
#define inc(i,l,r) for(int i=l;i<=r;i++)
const int MAXN=3e5+10;
using namespace std;
const ll inf=1e18;
const ll MOD=1e9+7;
vector<int>vec[MAXN];
int f[MAXN][21];int dep[MAXN];
int st[MAXN],tot;
int p[MAXN],cnt1;
vector<int>V;
bool vis[MAXN];
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return f*x;
}
ll Add(ll a, ll b){a+=b;if(a>=MOD)a-=MOD; return a;}
ll Mult(ll a, ll b){return (a*b)%MOD;}
void dfs(int v,int pre,int deep){
    dep[v]=deep;f[v][0]=pre;p[v]=++cnt1;
    for(int i=0;i<vec[v].size();i++){
    int u=vec[v][i];
    if(u!=pre){
        dfs(u,v,deep+1);
    }
    }
}
void dfs1(int v){
    inc(i,1,20)f[v][i]=f[f[v][i-1]][i-1];
    for(int i=0;i<vec[v].size();i++){
    int u=vec[v][i];
    if(u!=f[v][0])dfs1(u);
    }
}
int Lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    int tmp=dep[u]-dep[v];
    for(int i=0;i<=20;i++)if(tmp&(1<<i))u=f[u][i];
    if(u==v)return u;
    for(int i=20;i>=0;i--){
    if(f[u][i]!=f[v][i]){
        u=f[u][i];
        v=f[v][i];
    }
    }
    return f[u][0];
}
ll dp[2][305];
void built(int x){
    V.push_back(x);
    if(!tot){st[++tot]=x;return ;}
    int lca=Lca(x,st[tot]);
    while(tot>1&&dep[lca]<dep[st[tot-1]]){
    vec[st[tot]].push_back(st[tot-1]);
    vec[st[tot-1]].push_back(st[tot]);
    tot--;
    }
    if(dep[st[tot]]>dep[lca]){
    vec[st[tot]].push_back(lca);
    vec[lca].push_back(st[tot]);
    tot--;
    V.push_back(lca);
    }
    if(!tot||dep[lca]>dep[st[tot]])st[++tot]=lca;
    st[++tot]=x;
}
int M[MAXN],St[MAXN],cnt;
void dfs2(int x,int pre,int deep){
    if(vis[x])M[x]=deep+1,St[++cnt]=x;
    for(int i=0;i<vec[x].size();i++){
	if(vec[x][i]!=pre){
	    if(vis[x])dfs2(vec[x][i],x,deep+1);
	    else dfs2(vec[x][i],x,deep);
	}
    }
}
int n,m;
bool cmp(int aa,int bb){return p[aa]<p[bb];}
int main(){
    n=read();m=read();
    int u,v;
    for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
    dfs(1,0,0);dfs1(1);int k,q,r;
    for(int i=1;i<=n;i++)vec[i].clear();
    while(m--){
    k=read();q=read();r=read();
    tot=0;
    V.push_back(r);
    for(int i=1;i<=k;i++)v=read(),V.push_back(v),vis[v]=1;
    sort(V.begin(),V.end(),cmp);
    int sz=unique(V.begin(),V.end())-V.begin();
    for(int i=1;i<=sz;i++)built(V[i-1]);
    while(tot>1){vec[st[tot]].push_back(st[tot-1]),vec[st[tot-1]].push_back(st[tot]);tot--;}
    cnt=0;dfs2(r,0,0);
    int K=0;
    inc(i,1,q)dp[K][i]=0;
    dp[K][0]=1;
    for(int i=1;i<=cnt;i++){
	K=1-K;
	inc(j,0,q)dp[K][j]=0;
	for(int j=0;j<=q;j++){
	    if(j<q)dp[K][j+1]=Add(dp[K][j+1],dp[!K][j]);
	    if(M[St[i]]<=j)dp[K][j]=Add(dp[K][j],Mult(dp[!K][j],j-M[St[i]]+1));
	}
    }
    ll ans=0;
    inc(i,1,q)ans=Add(ans,dp[K][i]);
    printf("%lld\n",ans);
    for(int i=0;i<V.size();i++)vec[V[i]].clear(),vis[V[i]]=0;
    V.clear();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wang9897/p/10352125.html

时间: 2024-08-30 07:45:48

[codeforces]Round #537 (Div. 2)E. Tree的相关文章

CodeCraft-19 and Codeforces Round #537 (Div. 2) - D. Destroy the Colony(动态规划+组合数学)

Problem  CodeCraft-19 and Codeforces Round #537 (Div. 2) - D. Destroy the Colony Time Limit: 2000 mSec Problem Description Input Output For each question output the number of arrangements possible modulo 10^9+7. Sample Input abba21 41 2 Sample Output

Codeforces Round #540 (Div. 3) F1. Tree Cutting (Easy Version) 【DFS】

任意门:http://codeforces.com/contest/1118/problem/F1 F1. Tree Cutting (Easy Version) time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given an undirected tree of nn vertices. Some vert

Codeforces Round #629 (Div. 3) E. Tree Queries(lca题)

https://codeforces.com/contest/1328/problem/E E. Tree Queries You are given a rooted tree consisting of nn vertices numbered from 11 to nn. The root of the tree is a vertex number 11. A tree is a connected undirected graph with n−1n−1 edges. You are

Codeforces Round #316 (Div. 2) D. Tree Requests 树 离线在线 算法

D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of n vertices. Each vertex contains a lowercase English letter. Vertex 1 is the root of the

Codeforces Round #353 (Div. 2) D. Tree Construction (二分,stl_set)

题目链接:http://codeforces.com/problemset/problem/675/D 给你一个如题的二叉树,让你求出每个节点的父节点是多少. 用set来存储每个数,遍历到a[i]的时候查找比a[i]大的数的位置,然后插入,而父亲就是刚好比a[i]小的数或刚好大的数. 然后讨论是哪一个数. 比如给你3 1 2 ,如图 1的父亲是3 ,2的父亲是1. 那我其实只要找左边或右边出现最晚的数就行了,用pair的first表示a[i],second表示出现的顺序i. 1 #include

数据结构 - Codeforces Round #353 (Div. 2) D. Tree Construction

Tree Construction Problem's Link ---------------------------------------------------------------------------- Mean: 给定n个数,按照构造Binary Search Tree的方式来构造BST树,按顺序输出每一个非root结点的父节点的值. analyse: 构造BST树最坏情况下时间复杂度为O(n),肯定会超时. 注意到只需要输出结点的父节点的值,不需要真的构造BST树. 插到第i

CodeCraft-19 and Codeforces Round #537 (Div. 2)

A. Superhero Transformation 水题,注意两个字符串可能长度不相等. #include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100010; map<char ,int >m; int main(){ m['a']=m['e']=m['i']=m['o']=m['u']=1;

CodeCraft-19 and Codeforces Round #537 (Div. 2) 题解

传送门 D. Destroy the Colony 首先明确题意:除了规定的两种(或一种)字母要在同侧以外,其他字母也必须在同侧. 发现当每种字母在左/右边确定之后,方案数就确定了,就是分组的方案数乘\(\frac{((n/2)!)^2}{\prod cnt_i!}\). 分组的方案数考虑DP,设\(dp_{i,j}\)为前\(i\)个字母,占了左边\(j\)个位置的方案数,则有: \[ dp_{i,j}=dp_{i-1,j-cnt_i}+dp_{i-1,j} \] 当\(i\)是指定字母时特判

Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

https://codeforces.com/contest/1328/problem/E 题目所描述的是一棵树,题中已明示1为root结点. 题目可以转化为,是否存在一条路径,满足集合中的k个点到路径的距离小于等于1? 思路: 1.首先倍增离线预处理出结点深度,便于后续在线询问LCA 2.对于每次的询问,依次扫描k个点.对于集合中的u和v两点,每次我们求出u和v的LCA,计算u和v到LCA的距离,如果u和v到LCA的距离同时大于1,那么说明无法找到一条路径,使得u和v到该路径链的距离小于等于1