ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【HDU5840】This world need more Zhu

2020-02-02 22:58:16  阅读:262  来源: 互联网

标签:int top 200010 tim edge query need HDU5840 more


题目描述

As we all know, Zhu is the most powerful man. He has the infinite power to protest the world. We need more men like Zhu!

In Duoladuo, this place is like a tree. There are \(n\) vertices and \(n−1\) edges. And the root is 1. Each vertex can reached by any other vertices. Each vertex has a people with value \(A_i\) named Zhu's believer.

Liao is a curious baby, he has \(m\) questions to ask Zhu. But now Zhu is busy, he wants you to help him answer Liao's questions.

Liao's question will be like "u v k".

That means Liao want to know the answer from following code:


  ans = 0; cnt = 0;

  for x in the shortest path from u to v {

    cnt++;
    
    if(cnt mod k == 0) ans = max(ans,a[x]);

  }

  print(ans).

Please read the hints for more details.

输入

In the first line contains a single positive integer \(T\), indicating number of test case.

In the second line there are two numbers \(n\), \(m. n\) is the size of Duoladuo, \(m\) is the number of Liao's questions.

The next line contains \(n\) integers \(A1,A2,...An\), means the value of ith vertex.

In the next \(n−1\) line contains tow numbers \(u, v\). It means there is an edge between vertex \(u\) and vertex \(v\).

The next \(m\) lines will be the Liao's question:

u v k

\(1≤T≤10,1≤n≤100000,1≤m≤100000,1≤u,v≤n,1≤k, A_i≤1000000000.\)

输出

For each case, output Case #i: (i is the number of the test case, from 1 to \(T\)).

Then, you need to output the answer for every Liao's questions.

Sample Input

1
5 5
1 2 4 1 2
1 2
2 3
3 4
4 5
1 1 1
1 3 2
1 3 100
1 5 2
1 3 1

Sample Output

Case #1:
1
2
0
2
4

Hint

In query 1,there are only one vertex in the path,so the answer is 1.

In query 2,there are three vertices in the path.But only the vertex 2 mod 2 equals to 0.

In query 3,there are three vertices in the path.But no vertices mod 100 equal to 0.

In query 4,there are five vertices in the path.There are two vertices mod 2 equal to 0.So the answer is max(a[2],a[4]) = 2.

In query 5,there are three vertices in the path.And all the vertices mod 1 equal to 0. So the answer is a[3] = 4.

翻译

哎呀,大概看看伪代码就猜得到啦~

给一棵树,每次在u,v路径上编号,u为1号,然后对于编号为k的倍数的,求他们的点权的最大值,没有就输出0。

题解

emmmm本题标准乱搞题 考场上谁会相信这种乱搞。。。

对于询问的k进行分类。显然当k比较大的时候,我们暴力往上跳是可以解决的,随机数据远远跑不满。

k比较小的时候,我们就按照深度%k的值建立k棵线段树,然后在对应的线段树上查找就好了

这里的k取了20,发现是可以AC的。

考场上应该不会有这么奇怪的题=_= 如果人家刚好每个询问都是k=21,然后u,v是一条长长的链,这个做法肯定T成狗

不过出题人也不一定猜得到你的k取多少/cy 所以这个就看RP了

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[200010];
int ans[200010];
struct qwq{
    int v;
    int nxt;
}edge[200010];
int head[200010];
int cnt;
void add(int u,int v){
    edge[++cnt].nxt=head[u];
    edge[cnt].v=v;
    head[u]=cnt;
}
int fa[200010];
int son[200010];
int siz[200010];
int dep[200010];
void dfs1(int u,int ff){
    siz[u]=1;
    for(int i=head[u];~i;i=edge[i].nxt){
        int v=edge[i].v;
        if(v==ff)continue;
        fa[v]=u;
        dep[v]=dep[u]+1;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])son[u]=v;
    }
}
int ind;
int tim[200010];
int rea[200010];
int top[200010];
void dfs2(int u,int tp){
    top[u]=tp;
    tim[u]=++ind;
    rea[tim[u]]=u;
    if(son[u]){
        dfs2(son[u],tp);
    }
    for(int i=head[u];~i;i=edge[i].nxt){
        int v=edge[i].v;
        if(v==son[u]||v==fa[u])continue;
        dfs2(v,v);
    }
}
int lca(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        u=fa[top[u]];
    }
    if(dep[u]<dep[v])swap(u,v);
    return v; 
}
namespace small{
    struct sque{
        int u,v;
        int id;
        sque(int uu,int vv,int idd){u=uu,v=vv,id=idd;}
    };
    vector<sque> sq[21];
    int rt[20];
    struct node{
        int ls,rs;
        int val;
    }t[2000010];
    int tot;
    void update(int &o,int l,int r,int x){
        if(!o)o=++tot;
        if(l==r){
            t[o].val=a[rea[l]];
            return;
        }
        int mid=(l+r)/2;
        if(x<=mid)update(t[o].ls,l,mid,x);
        else update(t[o].rs,mid+1,r,x);
        t[o].val=max(t[t[o].ls].val,t[t[o].rs].val);
    }
    int query(int o,int l,int r,int L,int R){
        if(!o)return 0;
        if(L<=l&&r<=R){
            return t[o].val;
        }
        int ret=0;
        int mid=(l+r)/2;
        if(L<=mid)ret=max(ret,query(t[o].ls,l,mid,L,R));
        if(mid<R)ret=max(ret,query(t[o].rs,mid+1,r,L,R));
        return ret;
    }
    int query(int u,int v,int k){
        int LCA=lca(u,v);
        int ou=rt[(dep[u]+1%k)],ov=rt[(dep[LCA]+k-(dep[u]-dep[LCA]+1)%k)%k];
        int ret=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]>dep[top[v]]){
                ret=max(ret,query(ou,1,n,tim[top[u]],tim[u]));
                u=fa[top[u]];
            }
            else {
                ret=max(ret,query(ov,1,n,tim[top[v]],tim[v]));
                v=fa[top[v]];
            }
        }
        if(dep[u]>dep[v]){
            ret=max(ret,query(ou,1,n,tim[v],tim[u]));
        }
        else {
            ret=max(ret,query(ov,1,n,tim[u],tim[v]));
        }
        return ret;
    }
    void gao(int k){
        tot=0;memset(t,0,sizeof(t));
        memset(rt,0,sizeof(rt));
        for(int i=1;i<=n;++i){
            update(rt[dep[i]%k],1,n,tim[i]);
        }
        for(int i=0;i<sq[k].size();++i){
            int u=sq[k][i].u,v=sq[k][i].v,id=sq[k][i].id;
            ans[id]=query(u,v,k);
        }
        sq[k].clear();
    }
}
namespace big{
    struct bque{
        int s,k;
        int tp;
        int id;
        bque(int ss,int kk,int tpp,int idd){s=ss,k=kk,tp=tpp,id=idd;} 
    };
    vector<bque> bq[200010];
    int top;
    int stk[200010];
    void dfs(int u,int f){
        stk[++top]=u;
        for(int i=0;i<bq[u].size();++i){
            int s=bq[u][i].s,k=bq[u][i].k,tp=bq[u][i].tp,id=bq[u][i].id;
            for(int j=top-s;j>0&&dep[stk[j]]>=dep[tp];j-=k){
                ans[id]=max(ans[id],a[stk[j]]);
            }
        }
        bq[u].clear();
        for(int i=head[u];~i;i=edge[i].nxt){
            int v=edge[i].v;
            if(v==f)continue;
            dfs(v,u);
        }
        top--;
    }
}
int sb=0;
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("my.txt","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--){
        printf("Case #%d:\n",++sb);
        cnt=-1;
        memset(head,-1,sizeof(head));
        memset(ans,0,sizeof(ans));
        dep[1]=0;
        memset(son,0,sizeof(son));
        ind=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<n;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        dfs1(1,-1);
        dfs2(1,1);
        for(int i=1;i<=m;++i){
            int u,v,k;
            scanf("%d%d%d",&u,&v,&k);
            if(k<=20){
                small::sq[k].push_back(small::sque(u,v,i));
            }
            else {
                int LCA=lca(u,v);
                big::bq[u].push_back(big::bque(k-1,k,LCA,i));
                big::bq[v].push_back(big::bque((dep[u]+dep[v]-2*dep[LCA]+1)%k,k,LCA,i));
            }
        }
        for(int i=1;i<=20;++i){
            if(small::sq[i].size())small::gao(i);
        }
        big::dfs(1,-1);
        for(int i=1;i<=m;++i){
            printf("%d\n",ans[i]);
        }
    }
}

标签:int,top,200010,tim,edge,query,need,HDU5840,more
来源: https://www.cnblogs.com/youddjxd/p/12254120.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有