zoukankan      html  css  js  c++  java
  • BZOJ3251 树上三角形

      以传统的维护思路特别不可做。完全想不到的一点是,如果构造一个int内的数列使其中任意三个数都不能构成三角形,项数最多的方案显然是斐波拉契数列,而斐波拉契数列的项数显然是log级的。那么我们求出询问点之间的距离,如果超过项数直接输出,否则暴力判断即可。

      开始算距离的时候没把lca*2调了半天,而且明明可以暴力的为什么还写倍增啊。大概脑子坏了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100010
    #define int unsigned int
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,a[N],p[N],fa[N][18],deep[N],q[61],t=0;
    struct data{int to,nxt;
    }edge[N];
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void dfs(int k)
    {
        for (int i=p[k];i;i=edge[i].nxt)
        if (edge[i].to!=fa[k][0])
        {
            deep[edge[i].to]=deep[k]+1;
            dfs(edge[i].to);
        }
    }
    int lca(int x,int y)
    {
        if (deep[x]<deep[y]) swap(x,y);
        for (int j=17;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j];
        if (x==y) return x;
        for (int j=17;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
        return fa[x][0];
    }
    signed main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3251.in","r",stdin);
        freopen("bzoj3251.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++) a[i]=read();
        for (int i=1;i<n;i++)
        {
            int x=read(),y=read();
            addedge(x,y);fa[y][0]=x;
        }
        fa[1][0]=1;
        for (int j=1;j<18;j++)
            for (int i=1;i<=n;i++)
            fa[i][j]=fa[fa[i][j-1]][j-1];
        dfs(1);
        while (m--)
        {
            int op=read(),x=read(),y=read();
            if (op==0)
            {
                int l=lca(x,y);
                if (deep[x]+deep[y]-(deep[l]<<1)>60) printf("Y
    ");
                else
                {
                    int cnt=0;
                    while (x!=l) q[++cnt]=a[x],x=fa[x][0];
                    while (y!=l) q[++cnt]=a[y],y=fa[y][0];
                    q[++cnt]=a[l];
                    sort(q+1,q+cnt+1);
                    bool flag=1;
                    for (int i=1;i<=cnt-2;i++)
                    if (q[i]+q[i+1]>q[i+2]) {flag=0;break;}
                    if (flag) printf("N
    ");
                    else printf("Y
    ");
                }
            }
            else a[x]=y;
        }
        return 0;
    }
  • 相关阅读:
    使用C#编写SqlHelper类
    编译器perspective oo 对象模型(1) 之 初窥c++对象模型
    浅谈 编译器 & 自然语言处理
    基于c#的角色扮演游戏设计与实现
    开源的EtherCAT Master简介
    如何在Windows中编译Linux Unix的代码(采用cygwin)?
    sql拼语句例子
    IOC介绍-手写一个简单的IOC
    protocalBuffer_java版详解(转thanks)
    ProtocalBuffer_数据结构(转thanks)
  • 原文地址:https://www.cnblogs.com/Gloid/p/9676770.html
Copyright © 2011-2022 走看看