hiho11周树的直径

任意找一个点做根, 然后找到距离这个根最远的点,然后以这个点做根,再找距离这个根最远的点,两个距离和就是 树的直径。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<stdlib.h>
using namespace std;
typedef long long LL;

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1

const int maxn = 1000000 + 1000;
int sum[maxn << 2];
const int INF = 1<<30;
int ncnt;
int val[maxn];
int pos[maxn];

void up(int rt){
    sum[rt] = min(sum[rt << 1], sum[rt << 1 | 1]);
}

void build(int l, int r, int rt)
{
    sum[rt] = INF;
    if (l == r){
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    up(rt);
}

void update(int key, int l, int r, int rt)
{
    if (l == r){
        sum[rt] = key; return;
    }
    int mid = (l + r) >> 1;
    if (key <= mid) update(key, lson);
    else update(key, rson);
    up(rt);
}

int ask(int L, int R, int l, int r, int rt)
{
    if (L <= l&&r <= R) return sum[rt];
    int ans = INF;
    int mid = (l + r) >> 1;
    if (L <= mid) ans = min(ans, ask(L, R, lson));
    if (R > mid) ans = min(ans, ask(L, R, rson));
    return ans;
}

void gao(int x)
{
    int Min = INF; int ans=INF;
    for (int i = ncnt - 1; i >= 1; i--){
        if (val[i] % x == 0) {
            printf("%d\n", i); return ;
        }
        if (val[i] % x < Min){
            Min = val[i] % x;
            ans = i;
        }
    }
    printf("%d\n", ans);
}

void gao1(int x)
{
    int l = 0; int r = x - 1; int ans = -1;
    while (l <= maxn){
        if (r > maxn) r = maxn;
        int temp = ask(l, r, 0, maxn, 1);
        if(temp!=INF){
        if (ans==-1||temp%x < ans%x) ans = temp;
        else if (temp%x == ans%x&&pos[temp]>pos[ans])
            ans = temp;
        }
        l += x; r += x;
    }
    printf("%d\n", pos[ans]);
}

int main()
{
    char str[100];
    int k;
    int cnt = 0;
    int T;
    while (scanf("%d",&T),T){
        if(cnt) puts("");
        ncnt = 1;
        build(0, maxn, 1);
        printf("Case %d:\n", ++cnt);
        while (T--){
            scanf("%s%d", str, &k);
            if (str[0] == ‘B‘){
                val[ncnt] = k;
                pos[k] = ncnt++;
                update(k, 0, maxn, 1);
            }
            else{
                if(ncnt==1){
                    printf("-1\n");
                }
                else
                if (k < 10000) gao(k);
                else gao1(k);
            }
        }
    }
    return 0;
}
时间: 2024-08-04 13:34:24

hiho11周树的直径的相关文章

poj 1985 Cow Marathon 【树的直径】

题目:poj 1985 Cow Marathon 题意:给出一个树,让你求树的直径. 分析: 树的直径:树上两点之间的最大距离. 我们从任意一点出发,BFS一个最远距离,然后从这个点出发,在BFS一个最远距离,就是树的直径. AC代码: /* POJ:1985 Cow Marathon 2014/10/12/21:18 Yougth*/ #include <cstdio> #include <iostream> #include <algorithm> #include

poj1849(求树的直径)

题目链接:http://poj.org/problem?id=1849 题意:有一颗n个结点的带权的无向树, 在s结点放两个机器人, 这两个机器人会把树的每条边都走一遍, 但是最后机器人不要求回到出发点. 问你两个机器人走的路总长之和的最小值是多少? 分析:如果从某点出发遍历完一棵树再回来,那么所有边都会走两遍,而从某点有两个机器人出发去遍历,因为不用回来,所以最后那两个人距离越远越好,可以从树的直径上某个点背道而驰,那么这段距离(树的直径)只走了一遍,其他的要走两遍,所以ans=sum*2-l

SDUT OJ 3045 迷之图论 (树的直径)

题目地址:SDUT OJ 3045 这题比赛的时候想的差不多..但是总是觉得不对..写了一次就没再写,然后删了..当时没想到的是第二次求出来的就是最长链..当时想到的两次bfs找最大值(这一种方法其实结果也对..TAT..),还有找到点后在回溯减去重点等等..但总觉得好像都不太对...赛后才知道这题原来是树的直径.....牡丹江区域现场赛的时候遇到过,不过赛后也没看... 找树的直径的方法其实就是先任取一点进行bfs,找到最远的一点,这时最远的一点肯定是最长链端点之一,然后再从这一最远点开始bf

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

ZOJ Problem Set - 3820 Building Fire Stations 【树的直径 + 操作 】

题目:problemId=5374" target="_blank">ZOJ Problem Set - 3820 Building Fire Stations 题意:给出n个点,n-1条边的一棵树.然后要在两个点上建立两个消防站.让全部点的到消防站最大距离的点的这个距离最小. 分析:首先先求这个树的直径.然后在树的直径的中点处把树分成两棵树.然后在把两棵树分别取中点的最大值就是ans值. 这个题目数据有点水了感觉... AC代码: #include <cstdi

BDFZOI 树的直径

提交次数:2 涉及知识:基础图论/BFS 描述 一棵树T的"直径"定义为结点两两间距离的最大值.给定带权树T,求T的直径长度. 输入 第一行包含2个整数N.M,表示图中共有N个结点和M条无向边.(N <= 5000,M<n)接下来M行,每行包含3个整数{u,v,w},表示有一条无向边连接结点u.v*输入保证是无环图输出一个整数,代表直径长度 样例输入 4 31 2 12 3 22 4 3 样例输出 5 代码: 1 #include<iostream> 2 #in

codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relayi

hdu 4607(树的直径)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题解:给定一棵树,从树中的任意选一个顶点出发,遍历K个点的最短距离是多少?(每条边的长度为1) 算法分析: 首先如果k小于等于直径长度,那么答案为k−1;如果k大于直径长度,设直径长度为r,那么答案为r−1+(k−r)*2;树的直径:树上的最长简单路径; 代码: 1 #include <cstdio> 2 #include <cmath> 3 #include <cstri

BZOJ 2282 &amp; 树的直径

SDOI2011的Dayx第2题 题意: 在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在链上的点与这条链的距离最大值最小. SOL: 最大值最小!这不是二分的节奏么?然而hzw学长说二分更直观我却一点都没有体会到... 这道题的关键是猜想(貌似还挺好想)并证明(貌似一直都是可有可无的东西,不过还挺好证的),路径一定在直径上,那么我们先两遍*FS找到直径,用一个队列维护链上的路径,以及预