HDU6162(树链剖分)

28 篇文章 0 订阅
19 篇文章 0 订阅

难受,翻了各种傻逼错误,导致现在才改完

(函数没return,样例忘了换行,多余输出忘了删,估计是太晚了,脑子已经瓦特了)

,,,,

昨天是2018WF  莫斯科拿了一个冠军一个亚军,北大主场拿了季军。


这是一个树链剖分裸题,但是以前没看过,还比较简单,

来几个博客

点击打开链接

点击打开链接

;此题借鉴点击打开链接



#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<vector>

using namespace std;

const int maxn = 1e5+7;

vector<int> eg[maxn];
int top[maxn];

int siz[maxn];
int son[maxn];
int tid[maxn];
int ran[maxn];
int dep[maxn];
int fa[maxn];
int cnt,n;
long long  val[maxn];
long long  s[maxn];
long long tree[maxn*4],mx[maxn*4],mn[maxn*4];
void init()
{
    memset(son,-1,sizeof(son));
    memset(siz,0,sizeof(siz));
    memset(fa,0,sizeof(fa));
    memset(tid,0,sizeof(tid));
}
void dfs1(int u,int f,int d)
{
    //cout<<".."<<u<<endl;
    dep[u]=d;
    siz[u]=1;
    fa[u]=f;
    for(int i=0;i<eg[u].size();i++)
    {
        int v=eg[u][i];
        if(v==f)
            continue;
        if(!siz[v])
        {
            dfs1(v,u,d+1);
            siz[u]+=siz[v];
            if(son[u]==-1||siz[v]>siz[son[u]])
            {
                son[u]=v;
            }
        }
    }

}
void dfs2(int u,int tp)
{
    //cout<<u<<endl;
    top[u]=tp;
    tid[u]=++cnt;
    if(son[u]!=-1)
       dfs2(son[u],tp);
    for(int i=0;i<eg[u].size();i++)
    {
        int v=eg[u][i];
        if(v==fa[u]||son[u]==v) continue;
        if(!tid[v])
          dfs2(v,v);
    }
}
void gettree()
{
    dfs1(1,0,0);
    cnt=0;
    dfs2(1,1);

    for(int i=1;i<=n;i++)
    {
       // cout<<tid[i]<<" "<<top[i]<<" "<<son[i]<<endl;
        val[tid[i]]=s[i];
    }
   // cout<<"--"<<endl;
}
void build(int root,int l,int r)
{
    if(l==r)
    {
        tree[root]=mx[root]=mn[root]=val[l];
        return;
    }
    int mid=(l+r)>>1;
    build(root*2,l,mid);
    build(root*2+1,mid+1,r);
    tree[root]=tree[root*2]+tree[root*2+1];
    mx[root]=max(mx[root*2],mx[root*2+1]);
    mn[root]=min(mn[root*2],mn[root*2+1]);
}

long long query(int root,int l,int r,int ql,int qr,long long a,long long  b)
{
  //  if(ql>r||qr<l)
    //    return 0;

     if(ql<=l&&qr>=r)
    {
        //if(mn[root]>b||mx[root]<a)
          //  return 0;
        if(mn[root]>b||mx[root]<a)
            return 0;  //还有半个的情况
        if(mx[root]<=b&&mn[root]>=a)
            return tree[root];
        
    }
    int mid=(l+r)>>1;
    long long ans=0;
    if(ql<=mid)
        ans+=query(root*2,l,mid,ql,qr,a,b);
    if(qr>mid)
        ans+=query(root*2+1,mid+1,r,ql,qr,a,b);
    //cout<<ans<<endl;
    return ans;
}
long long solve(int u,int v,long long a,long long b)
{
    int top1=top[u],top2=top[v];
    long long ans=0;
    while(top1!=top2)
    {
        if(dep[top1]<dep[top2])
        {
            swap(top1,top2);
            swap(u,v);
        }
       // cout<<u<<v<<endl;
        ans+=query(1,1,n,tid[top1],tid[u],a,b);
        u=fa[top1];
        top1=top[u];
    }
    if(u==v)
    {
        //cout<<"."<<u<<endl;
        if(s[u]>=a&&s[u]<=b)
            ans+=s[u];
            //cout<<","<<ans<<endl;
        return ans;
    }
    if(dep[u]>dep[v])
        swap(u,v); //cout<<","<<ans<<" "<<tid[u]<<" "<<tid[v]<<endl;
    ans+=query(1,1,n,tid[u],tid[v],a,b);

    return ans;
}
int main()
{
    int m;
    while(~scanf("%d%d",&n,&m))
    {
        cnt=0;
        init();
        for(int i=0;i<=n;i++)
        {
            eg[i].clear();
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%lld",&s[i]);
        }
        for(int i=0; i<n-1; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            eg[x].push_back(y);
            eg[y].push_back(x);
        }
        gettree();
        build(1,1,n);
        for(int i=0;i<m;i++)
        {
            int x,y;
            long long a,b;
            scanf("%d%d%lld%lld",&x,&y,&a,&b);
            if(i!=0)
                printf(" ");
            printf("%lld",solve(x,y,a,b));
        }
        printf("\n");
    }
    return 0;
}
wa的可太惨了,睡觉
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值