这题用线段树错了?
查看原帖
这题用线段树错了?
305891
夜明楼主2021/10/31 20:29
#include<iostream>
#include<cstdio>
using namespace std;
const int Maxn=2*1e9;
int dis[20005],cst[20005],rg[20005],wst[20005],dp[20005],st[20005],ed[20005];
struct segTree{
    int l,r;
    int lz;
    int minn;
}tree[80005];
int num[20005];
struct node{
    int end;
    int nxt;
    int id;
    void add(int u,int v,int w){
        end=v;
        nxt=num[u];
        num[u]=w;
        id=w;
    }
}Edge[20005];
int binarySearch_min(int n,int x){
    int l=1,r=n,ans=0;
    while(l<=r){
        int mid=(l+r)/2;
        if(dis[mid]<x)
            l=mid+1,ans=mid;
        else
            r=mid-1;
    }
    return ans;
}
int binarySearch_max(int n,int x){
    int l=1,r=n,ans=n+1;
    while(l<=r){
        int mid=(l+r)/2;
        if(dis[mid]>x)
            r=mid-1,ans=mid;
        else
            l=mid+1;
    }
    return ans;
}
void Init(int n){
    for(int i=1;i<=n;i++)
        dp[i]=dp[i-1]+wst[i];
    for(int i=1;i<=n;i++)
        st[i]=binarySearch_min(n,dis[i]-rg[i]);
    for(int i=1;i<=n;i++)
        ed[i]=binarySearch_max(n,dis[i]+rg[i]);
    for(int i=1;i<=n;i++)
        Edge[i].add(ed[i],st[i],i);
}
void Build(int k,int l,int r){
    tree[k].l=l;
    tree[k].r=r;
    if(l==r){
        tree[k].minn=dp[l];
        return;
    }
    int mid,lc,rc;
    mid=(l+r)/2;
    lc=2*k,rc=2*k+1;
    Build(lc,l,mid);
    Build(rc,mid+1,r);
    tree[k].minn=min(tree[lc].minn,tree[rc].minn);
}
void Lazy(int k,int v){
    tree[k].minn+=v;
    tree[k].lz+=v; 
}
void Pushdown(int k){
    int v=tree[k].lz;
    Lazy(2*k,v);
    Lazy(2*k+1,v);
    tree[k].lz=0;
}
void Pushup(int k){
    int lc,rc;
    lc=2*k,rc=2*k+1;
    tree[k].minn=min(tree[lc].minn,tree[rc].minn);
}
void Update(int k,int l,int r,int v){
    if(l<=tree[k].l&&r>=tree[k].r)
        return Lazy(k,v);
    Pushdown(k);
    int mid,lc,rc;
    mid=(tree[k].l+tree[k].r)/2;
    lc=2*k,rc=2*k+1;
    if(l<=mid)
        Update(lc,l,r,v);
    if(r>mid)
        Update(rc,l,r,v);
    Pushup(k);
}
int Query(int k,int l,int r){
    if(l<=tree[k].l&&r>=tree[k].r)
        return tree[k].minn;
    int mid,lc,rc,ans=Maxn;
    mid=(tree[k].l+tree[k].r)/2;
    lc=2*k,rc=2*k+1;
    if(l<=mid)
        ans=min(ans,Query(lc,l,r));
    if(r>mid)
        ans=min(ans,Query(rc,l,r));
    return ans;
}
void Read(int n,int k){
    for(int i=2;i<=n;i++)
        scanf("%d",&dis[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&cst[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&rg[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&wst[i]);
}
int Solve(int n,int k){
    int ans=dp[n]; 
    for(int i=1;i<=k;i++){
        Build(1,1,n);
        for(int j=1;j<=n;j++){
            for(int h=num[j];h;h=Edge[h].nxt){
                int y=Edge[h].end;
                int id=Edge[h].id;
                if(y>0)
                    Update(1,1,y,wst[id]);
            }
            if(j>i)
                dp[j]=min(Query(1,1,j)+cst[j],dp[j]);
            else
                dp[j]=min(dp[j],cst[j]);
        }
        ans=min(ans,dp[n]);
    }
    return ans;
}
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    Read(n,k);
    Init(n);
    printf("%d\n",Solve(n,k));
    return 0;
}
2021/10/31 20:29
加载中...