Codeforces418D Big Problems for Organizers

原创 2016年06月01日 20:44:08

题目链接

题目大意

给定一棵n个节点的树,m次询问,每次给出两个点u,v,求

max{min(dist(i,u),dist(i,v))}.

n,m105.

解题思路

并没有什么思路…甚至还想过块状树…
可以用树的直径来做.
首先把直径从树中抽出来重新编号,把其他的点都变为挂在直径上的某个点上,只需维护每个节点属于的直径上的节点编号以及这两点间的距离,还有直径上节点到挂在它上面的点的最大距离.
然后询问时各种分类讨论,列出表达式变量分离RMQ什么的….
细节巨多,这里空太小,写不下.
于是用ST表可以达到一个奇妙的复杂度:
O(nlgn)预处理,O(1)查询.
bblss123还有倍增的做法.

丑丑的代码君

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5,LG=18,INF=1e9;
int n,tot_edge,tot,mx_dis,ID,head[N],pre[N],id[N],dep[N],mx_dep[N],lg[N],arr[N],
    ST[2][N][LG];
struct Edge{
    int to,nxt;
}edge[N<<1];
inline void add_edge(int from,int to){
    edge[tot_edge]=(Edge){to,head[from]};
    head[from]=tot_edge++;
}
void rd(int &res){
    res=0;
    char c;
    while(c=getchar(),c<48);
    do res=(res<<3)+(res<<1)+(c^48);
        while(c=getchar(),c>47);
}
inline void Max(int &a,int b){
    if(b>a)a=b;
}
void dfs(int cur,int par,int depth){
    if(depth>=mx_dis){
        mx_dis=depth;
        ID=cur;
    }
    pre[cur]=par;
    for(int i=head[cur];~i;i=edge[i].nxt){
        int to=edge[i].to;
        if(to==par)continue;
        dfs(to,cur,depth+1);
    }
}
void assign_dfs(int cur,int belong,int depth){
    id[cur]=belong;
    Max(mx_dep[belong],dep[cur]=depth);
    for(int i=head[cur];~i;i=edge[i].nxt){
        int to=edge[i].to;
        if(~id[to])continue;
        assign_dfs(to,belong,depth+1);
    }
}
void assign(){
    memset(id,-1,n+1<<2);
    for(int cur=ID,cnt=0;~cur;cur=pre[cur]){
        id[cur]=cnt;
        arr[cnt++]=cur;
    }
    tot=mx_dis+1;
    for(int i=0;i<tot;++i)
        assign_dfs(arr[i],i,0);
}
void init(){
    mx_dis=ID=-1;
    dfs(1,-1,0);
    dfs(ID,-1,0);
    assign();
    for(int i=0;i<tot;++i){
        ST[0][i][0]=mx_dep[i]-i;
        ST[1][i][0]=mx_dep[i]+i;
    }
    for(int j=1;1<<j<=tot;++j)
        for(int i=0;i+(1<<j)<=tot;++i)
            for(int k=0;k<2;++k)
                ST[k][i][j]=max(ST[k][i][j-1],ST[k][i+(1<<j-1)][j-1]);
    for(int i=2,j=1;i<=tot+1;++i){
        lg[i]=j;
        if(!(i&(i-1)))++j;
    }
}
int query_mx(bool type,int L,int R){
    if(L>R)return -INF;
    int k=lg[R-L+2]-1;
    return max(ST[type][L][k],ST[type][R-(1<<k)+1][k]);
}
int solve(int u,int v){
    if(id[u]==id[v]){
        if(dep[u]>dep[v])swap(u,v);
        return max(id[u],tot-1-id[u])+dep[u];
    }
    if(id[u]>id[v])swap(u,v);
    int mid=id[u]-dep[u]+id[v]+dep[v]>>1,ans=0;
    if(mid<id[u]){
        Max(ans,query_mx(0,0,id[v]-1)+id[v]+dep[v]);
        Max(ans,dep[v]);
        Max(ans,query_mx(1,id[v]+1,tot-1)-id[v]+dep[v]);
    }
    else if(mid>=id[v]){
        Max(ans,query_mx(0,0,id[u]-1)+id[u]+dep[u]);
        Max(ans,dep[u]);
        Max(ans,query_mx(1,id[u]+1,tot-1)-id[u]+dep[u]);
    }
    else{
        Max(ans,query_mx(0,0,id[u]-1)+id[u]+dep[u]);
        Max(ans,dep[u]);
        Max(ans,query_mx(1,id[u]+1,mid)-id[u]+dep[u]);
        Max(ans,query_mx(0,mid+1,id[v]-1)+id[v]+dep[v]);
        Max(ans,dep[v]);
        Max(ans,query_mx(1,id[v]+1,tot-1)-id[v]+dep[v]);
    }
    return ans;
}
int main(){
    int sz=128<<20;
    char *p=(char*)malloc(sz)+sz;
    __asm__("movl %0, %%esp\n" :: "r"(p));
    int m,u,v;
    rd(n);
    tot_edge=0;
    memset(head,-1,n+1<<2);
    for(int i=1;i<n;++i){
        rd(u);rd(v);
        add_edge(u,v);
        add_edge(v,u);
    }
    init();
    rd(m);
    while(m--){
        rd(u);rd(v);
        printf("%d\n",solve(u,v));
    }
    return 0;
}
/*

    Jun.01.16

    Tags:Tree
    Submissions:4

    Time 93ms
    Memory 151600KB

*/
版权声明:原创文章,转载请注明出处哟~~

相关文章推荐

Codeforces Round #418 (Div. 2) D. An overnight dance in discotheque 贪心

题目链接: An overnight dance in discotheque题目大意n个圆, 他们相互之间相切相离包含, 但不会相交一幅图的总面积等于图中阴影面积 就是被包含偶数次的圆内为阴影,...

Codeforces Round #418 (Div. 2) D. An overnight dance in discotheque(思维 贪心)

题意:有很多人跳舞,跳舞范围是个圆,然后跳舞的人分上半夜和下半夜,同一个圈圈里面的人不能同时跳。让你把所有能跳圈圈的面积加起来,得到的面积最大。 (所有圆之间只有包含和不想交关系。没有相交) ...

Codeforces 673B Problems for Round【思维】

B. Problems for Round time limit per test 2 seconds memory limit per test 256 megabytes i...

Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) B.Problems for Round

B. Problems for Round time limit per test 2 seconds memory limit per test 256 megabytes ...

【codeforces 757D】Felicity's Big Secret Revealed

【题目链接】:http://codeforces.com/problemset/problem/757/D【题意】 给你一个01串; 让你分割这个01串; 要求2切..n+1切; 对于每一...

Codeforces Round #418 (Div. 2)

A. An abandoned sentiment from past 题意:给你一个含有n个数的序列,其中有k个数为0,再给你k个数,让你将序列中的0用这k个数代替,每个数只能用一次,问你能不能使替...

Codeforces Round #418 (Div. 2) C 预处理/思维题

题目链接题意很简单,我一开始的思路是填两个相同字母之间的缝隙: 预处理每个字母出现的位置,然后在线处理询问,从左到右枚举起点,用可以填补的字母填补缝隙,维护最长长度。加上各种优化以后复杂度O(NQ)...

CF-Codeforces Round #418 (Div. 2)-C-An impassioned circulation of affection

ACM模版描述 题解对于这种海量查询的问题,不用多想,99 成需要预处理,而常见的预处理手段除了线段树、树状数组、RMQ 之类,还有 DP 等等,这里用的就是 DP 预处理。设 dp[i][j]dp...
  • f_zyj
  • f_zyj
  • 2017-06-16 00:09
  • 162

Codeforces Round #418 (Div. 2) problem A. An abandoned sentiment from past

A. An abandoned sentiment from past time limit per test 1 second memory limit per test 256 megab...

Codeforces Round #418 (Div. 2) problem B. An express train to reveries

B. An express train to reveries time limit per test 1 second memory limit per test 256 megabytes...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)