zoukankan      html  css  js  c++  java
  • BZOJ 1468 Tree(点分治+双指针 模板题)

    Description

    给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

    Input

    N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

    Output

    一行,有多少对点之间的距离小于等于k

    Sample Input

    7
    1 6 13 
    6 3 9 
    3 5 7 
    4 1 3 
    2 4 20 
    4 7 2 
    10

    Sample Output

    5

    Hint

    Source

    LTC男人八题系列

    题解:模板题,点分治+双指针

    #include <bits/stdc++.h>
    #define IO_read ios::sync_with_stdio(false);cin.tie(0)
    #define fre freopen("in.txt", "r", stdin)
    #define _for(i,a,b) for(int i=a; i< b; i++)
    #define _rep(i,a,b) for(int i=a; i<=b; i++)
    #define inf 0x3f3f3f3f
    #define lowbit(a) ((a)&-(a))
    using namespace std;
    typedef long long ll;
    template <class T>
    void read(T &x)
    {
        char c; bool op=0;
        while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1;
        x=c-'0';
        while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0';
        if(op) x=-x;
    }
    template <class T>
    void write(T x)
    {
        if(x<0) putchar('-'), x=-x;
        if(x>=10) write(x/10);
        putchar('0'+x%10);
    }
    
    const int maxn=5e4+5;
    int head[maxn], tot;
    struct Edge{
        int to, next, val;
    }edge[maxn*2];
    
    void addedge(int u, int v, int w)
    {
        edge[++tot]={v, head[u], w};
        head[u]=tot;
    }
    
    int n, k;
    ll ans;
    int sz[maxn], vis[maxn], max_son, rt, Size;
    ll dis[maxn], q[maxn];
    int l, r;
    
    void get_rt(int u, int fa)
    {
        sz[u]=1;
        int num=0;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to;
            if(vis[v] || v==fa) continue;
            get_rt(v, u);
            sz[u]+=sz[v];
            num=max(num, sz[v]);
        }
        num=max(num, Size-sz[u]);
        if(num<max_son) max_son=num, rt=u;
    }
    
    void get_dis(int u, int fa)
    {
        q[++r]=dis[u];
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to, w=edge[i].val;
            if(vis[v] || v==fa) continue;
            dis[v]=dis[u]+w;
            get_dis(v, u);
        }
    }
    
    ll solve(int u, int val)
    {
        l=1, r=0, dis[u]=val;
        get_dis(u, 0);
        ll res=0;
        sort(q+1, q+r+1);
        while(l<r)  //双指针
        {
            if(q[l]+q[r]<=k) res+=r-l, ++l;
            else --r;
        }
        return res;
    }
    
    void divide(int u)
    {
        ans+=solve(u, 0);
        vis[u]=true;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].to, w=edge[i].val;
            if(vis[v]) continue;
            ans-=solve(v, w);  //容斥
            Size=sz[v], max_son=inf;
            get_rt(v, 0);
            divide(rt);
        }
    }
    
    int main()
    {
        IO_read;
        //fre;
        cin>>n;
        memset(head, -1, sizeof(head));
        for(int i=1,u,v,w; i<n; i++)
        {
            cin>>u>>v>>w;
            addedge(u, v, w), addedge(v, u, w);
        }
        cin>>k;
        Size=n, max_son=inf;
        get_rt(1, 0);
        divide(rt);
        cout<<ans<<"
    ";
    }
  • 相关阅读:
    python每隔半个小时执行一次实现思维
    计算机网络毕业论文3000字,给学弟做的作业
    计算机毕业论文总结_计算机应用毕业论文
    计算机毕业论文8000字_计算机应用毕业论文
    计算机专业论文3000字_计算机毕业论文8000字
    java浏览器_java游戏网站
    python定时器_python倒计时代码
    javascript语法基础_java教程
    javascript开发自学_没有基础的人学js
    JAVA怎么实现软件和驱动下载
  • 原文地址:https://www.cnblogs.com/Yokel062/p/11749245.html
Copyright © 2011-2022 走看看