UESTC 1558 线段树点更新

每次查找当前位置开始权值到结束权值之间最小时间,更新结束点的最小时间。

不过在建树的时候初始化写在if里面了,因此wrong了n次还蛋疼了一晚上。


ACcode:

#include<cstdio>
#include<iostream>
#include<algorithm>
using std::unique;
using std::sort;

typedef long long LL;
const int nsize=111111;
const LL INF=1000000000000000LL;

struct Item
{
    int v,u,t;
    bool operator < (const Item &cmp) const{
        return v<cmp.v;
    }
} item[nsize];

int X[nsize<<1];
LL sum[nsize<<3],t;

LL Min(LL a1,LL a2)
{
    return a1<a2? a1:a2;
}

void build(int rt,int l,int r)
{
    sum[rt]=INF;
    if (l==r) return ;
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
}

int Fin(int key,int len)
{
    int l=0,r=len;
    while (l<=r)
    {
        int m=(l+r)>>1;
        if (X[m]==key) return m;
        else if (X[m]<key) l=m+1;
        else r=m-1;
    }
    return -1;
}

void update(int rt,int l,int r,int p,LL v)
{
    if (l==r)
    {
        sum[rt]=Min(sum[rt],v);
        return ;
    }
    int m=(l+r)>>1;
    if (p<=m) update(rt<<1,l,m,p,v);
    else update(rt<<1|1,m+1,r,p,v);
    sum[rt]=Min(sum[rt<<1],sum[rt<<1|1]);
}

LL query(int rt,int l,int r,int L,int R)
{
    if (L<=l&&r<=R) return sum[rt];
    LL ans=INF;
    int m=(l+r)>>1;
    if (L<=m) ans=Min(ans,query(rt<<1,l,m,L,R));
    if (R>m)  ans=Min(ans,query(rt<<1|1,m+1,r,L,R));
    return ans;
}

int main()
{
    int T,top,cas=0;
    int i,n,m,L,R;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d %d",&n,&m);
        for (top=i=0; i<n; i++)
        {
            scanf("%d%d%d",&item[i].v,&item[i].u,&item[i].t);
            X[top++]=item[i].v;
            X[top++]=item[i].u;
        }
        X[top++]=m,X[top++]=1;
        sort(X,X+top);
        sort(item,item+n);
        top=unique(X,X+top)-X-1;
        build(1,0,top);
        update(1,0,top,0,0);
        printf("Case #%d: ",++cas);
        for (i=0; i<n; i++)
        {
            if (item[i].u>=item[i].v) continue;
            L=Fin(item[i].u,top);
            R=Fin(item[i].v,top);
            t=query(1,0,top,L,R-1);
            if (t>=INF) continue;
            update(1,0,top,R,t+(LL)item[i].t);
        }
        t=query(1,0,top,Fin(m,top),top);
        if (t==INF) t=-1;
        printf("%lld\n",t);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值