• [HDU4123]Bob’s Race


    题目大意:
    给定一棵$n$个点并且有边权的树,每个点的权值为该点能走的最远长度,并输入$m$个询问,每次询问最多有多少个编号连续的点,他们的最大最小点权差小于等于$Q$。

    思路:
    两趟DP(DFS)求出每个点能走的最远长度,然后用ST算法预处理出每一段最大最小值。
    对于每组询问,用尺取法求出最大值。
    注意log2不能用cmath里面的函数(尤其是不能在for语句上),不然会TLE,最好是自己实现。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<vector>
     4 inline int getint() {
     5     char ch;
     6     while(!isdigit(ch=getchar()));
     7     int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 inline int log2(const float x){
    12     return ((unsigned&)x>>23&255)-127;
    13 }
    14 const int N=50001,logN=16;
    15 struct Edge {
    16     int to,w;
    17 };
    18 std::vector<Edge> e[N];
    19 inline void add_edge(const int u,const int v,const int w) {
    20     e[u].push_back((Edge){v,w});
    21 }
    22 int w[N][3],son[N];
    23 void dfs1(const int x,const int par) {
    24     w[x][0]=w[x][1]=0;
    25     for(unsigned i=0;i<e[x].size();i++) {
    26         int &y=e[x][i].to;
    27         if(y==par) continue;
    28         dfs1(y,x);
    29         if(w[y][0]+e[x][i].w>w[x][0]) {
    30             w[x][1]=w[x][0];
    31             w[x][0]=w[y][0]+e[x][i].w;
    32             son[x]=y;
    33         }
    34         else if(w[y][0]+e[x][i].w>w[x][1]) {
    35             w[x][1]=w[y][0]+e[x][i].w;
    36         }
    37     }
    38 }
    39 void dfs2(const int x,const int par) {
    40     for(unsigned i=0;i<e[x].size();i++) {
    41         int &y=e[x][i].to;
    42         if(y==par) continue;
    43         w[y][2]=std::max(w[x][2],son[x]!=y?w[x][0]:w[x][1])+e[x][i].w;
    44         dfs2(y,x);
    45     }
    46 }
    47 int max[N][logN],min[N][logN];
    48 inline int getsum(const int l,const int r) {
    49     int k=log2(r-l+1);
    50     return std::max(max[l][k],max[r-(1<<k)+1][k])-std::min(min[l][k],min[r-(1<<k)+1][k]);
    51 }
    52 int main() {
    53     for(;;) {
    54         int n=getint(),m=getint();
    55         if(!n&&!m) return 0;
    56         for(int i=1;i<n;i++) {
    57             int u=getint(),v=getint(),w=getint();
    58             add_edge(u,v,w);
    59             add_edge(v,u,w);
    60         }
    61         dfs1(1,0);
    62         dfs2(1,0);
    63         for(int i=1;i<=n;i++) {
    64             max[i][0]=min[i][0]=std::max(w[i][0],w[i][2]);
    65         }
    66         for(int j=1;1<<j<=n;j++) {
    67             for(int i=1;i<=n-(1<<j)+1;i++) {
    68                 max[i][j]=std::max(max[i][j-1],max[i+(1<<(j-1))][j-1]);
    69                 min[i][j]=std::min(min[i][j-1],min[i+(1<<(j-1))][j-1]);
    70             }
    71         }
    72         while(m--) {
    73             int q=getint(),ans=0;
    74             for(int l=1,r=1;l<=r;l++) {
    75                 for(;r<=n&&getsum(l,r)<=q;r++);
    76                 ans=std::max(ans,r-l);
    77             }
    78             printf("%d
    ",ans);
    79         }
    80         for(int i=1;i<=n;i++) e[i].clear();
    81     }
    82 }
  • 相关阅读:
    电脑页面放到手机显示时,遇到了一个奇怪的问题:字体的显示大小,与在CSS中指定的大小不一致
    Win 7 安装VMware Workstation Pro 14出现 “Intel VT-x禁用”问题以及“无法连接 MKS: 套接字连接尝试次数太多;正在放弃”问题的实质性解决
    linux下文件权限777了,file_put_contents()却不能写入,为什么?
    Linux常用命令版本CentOS7.x
    sqlserver阻塞
    深入理解sqlserver日志-01
    CentOS添加和删除用户
    root修改sudoers文件
    linux常用命令-持续更新
    CentOS虚拟机设置IP
  • 原文地址:https://www.cnblogs.com/skylee03/p/7429190.html
Copyright © 2020-2023  润新知