Educational Codeforces Round 47 (Rated for Div. 2)F. Dominant Indices 线段树合并

题意:有一棵树,对于每个点求子树中离他深度最多的深度是多少,
题解:线段树合并快如闪电,每个节点开一个权值线段树,递归时合并即可,然后维护区间最多的是哪个权值,到x的深度就是到根的深度减去x到根的深度复杂度O(nlogn)

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
//#define vi vector<int>
#define mod 998244353
#define ld long double
#define C 0.5772156649
//#define ls l,m,rt<<1
//#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=1000000+10,maxn=50000+10,inf=0x3f3f3f3f;

vector<int> v[N];
int deep[N];
void dfs(int u,int f,int dep)
{
    deep[u]=dep;
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(x!=f)dfs(x,u,dep+1);
    }
}
int root[N],ma[N*22],ind[N*22];
int ls[N*22],rs[N*22],tot;
inline void pushup(int o)
{
    if(ma[ls[o]]>=ma[rs[o]])ma[o]=ma[ls[o]],ind[o]=ind[ls[o]];
    else ma[o]=ma[rs[o]],ind[o]=ind[rs[o]];
}
inline int Merge(int x,int y,int l,int r)
{
//    printf("%d----------------------------%d\n",l,r);
    if(l==r)
    {
        if(!x||!y)
        {
            ma[x+y]=ma[x]+ma[y];
//            printf("%d %d %d %d %d %d\n",x,ma[x],y,ma[y],l,r);
            return x+y;
        }
        else
        {
            ma[x]=ma[x]+ma[y];
//            printf("%d %d %d %d %d %d\n",x,ma[x],y,ma[y],l,r);
            return x;
        }
    }
    if(!x||!y)return x+y;
    int m=(l+r)>>1;
    ls[x]=Merge(ls[x],ls[y],l,m);
    rs[x]=Merge(rs[x],rs[y],m+1,r);
    pushup(x);
    return x;
}
void update(int &o,int pos,int l,int r)
{
    if(!o)o=++tot;
//    printf("%d %d %d %d---\n",l,r,pos,o);
    if(l==r){ma[o]++;ind[o]=l;return ;}
    int m=(l+r)>>1;
    if(pos<=m)update(ls[o],pos,l,m);
    else update(rs[o],pos,m+1,r);
    pushup(o);
}
void debug(int o,int l,int r)
{
//    printf("%d+++%d %d %d %d\n",o,ma[o],ind[o],l,r);
    if(l==r)return ;
    int m=(l+r)>>1;
    if(ls[o])debug(ls[o],l,m);
    if(rs[o])debug(rs[o],m+1,r);
}
int ans[N],n;
void solve(int u,int f)
{
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(x!=f)solve(x,u);
    }
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(x!=f)
        {
            root[u]=Merge(root[u],root[x],1,n);
//            puts("****************8");
//            debug(root[id[u]],1,n);
//            puts("!!!!!");
        }
    }
//    debug(root[id[u]],1,n);
//    puts("------------");
    ans[u]=ind[root[u]]-deep[u];
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        v[a].pb(b),v[b].pb(a);
    }
    dfs(1,-1,1);
    for(int i=1;i<=n;i++)
        update(root[i],deep[i],1,n);
    solve(1,-1);
    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
    return 0;
}
/********************
4
1 2
1 3
1 4
********************/

原文地址:https://www.cnblogs.com/acjiumeng/p/9339091.html

时间: 2024-11-06 07:35:47

Educational Codeforces Round 47 (Rated for Div. 2)F. Dominant Indices 线段树合并的相关文章

Educational Codeforces Round 81 (Rated for Div. 2)F(线段树)

预处理把左集划分为大小为1~i-1时,把全部元素都移动到右集的代价,记作sum[i]. 然后枚举终态时左集的大小,更新把元素i 留在/移动到 左集的代价. 树状数组/线段树处理区间修改/区间查询 1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int N=2e5+7; 6 struct Tree{ 7 ll minn,la

Educational Codeforces Round 47 (Rated for Div. 2) :E. Intercity Travelling

题目链接:http://codeforces.com/contest/1009/problem/E 解题心得: 一个比较简单的组合数学,还需要找一些规律,自己把方向想得差不多了但是硬是找不到规律,还是看了大佬博客才知道的规律.这个题要预先处理2的n次方,不然快速幂也会TLE. 推荐两个大佬的博客: https://blog.csdn.net/u010746456/article/details/81057082 https://blog.csdn.net/hyp1231/article/deta

Educational Codeforces Round 47 (Rated for Div. 2)G. Allowed Letters 网络流

题意:给你一个字符串,和每个位置可能的字符(没有就可以放任意字符)要求一个排列使得每个位置的字符在可能的字符中,求字典序最小的那个 题解:很容易判断有没有解,建6个点表示从a-f,和源点连边,容量为原串字符出现次数,再建64个点表示给定的位置的每一个状态,和汇点连边,容量为出现次数,如果a-f某个字符在状态中出现过,再把a-f和状态连边,容量inf,但是这只能求可行解,并不是字典序最小, 我们枚举每个位置该放哪个字符(a-f),假设该位置是pos,枚举的字符是x,该位置可能字符的状态是st,现在

Educational Codeforces Round 44 (Rated for Div. 2)+E. Pencils and Boxes+树状数组

题目链接:E. Pencils and Boxes 题意:N 个数,要求分成任意堆,要求每一堆只要有K个,同一堆中任意数之间差值不能超过d; 题解:用树状数组.排一下序然后从后面开始找,以当前数为最小值看能否成堆,要成堆的话要求i+k,到第一个大于a[i]+d的位置之间有能够成堆的位置.(这里判断的时候树状数组一减看是否大于0就可以了)注意初始化时在n+1的位置加1. 1 #include<bits/stdc++.h> 2 #include <iostream> 3 #includ

Educational Codeforces Round 61 (Rated for Div. 2)F(区间DP,思维,枚举)

#include<bits/stdc++.h>typedef long long ll;const int inf=0x3f3f3f3f;using namespace std;char b[507];int dp[507][507];int main(){    memset(dp,0x3f,sizeof(dp));    int n;    scanf("%d",&n);    scanf("%s",b+1);    for(int i=1;

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars There are n pillars aligned in a row and numbered from 1 to n. Initially each pillar contains exactly one disk. The i-th pillar contains a disk having radius ai. You can move these disks

Educational Codeforces Round 71 (Rated for Div. 2) A - There Are Two Types Of Burgers

原文链接:https://www.cnblogs.com/xwl3109377858/p/11404050.html Educational Codeforces Round 71 (Rated for Div. 2) A - There Are Two Types Of Burgers There are two types of burgers in your restaurant — hamburgers and chicken burgers! To assemble a hamburg

Educational Codeforces Round 71 (Rated for Div. 2) D - Number Of Permutations

原文链接:https://www.cnblogs.com/xwl3109377858/p/11405773.html Educational Codeforces Round 71 (Rated for Div. 2) D - Number Of Permutations You are given a sequence of n pairs of integers: (a1,b1),(a2,b2),…,(an,bn). This sequence is called bad if it is