UESTC 2020 Winter Training #1 Basic Data Structure【Animal Transport】

题意

四种物品, n n 个,每个有自己的起点和终点,相邻物品不能放一起。
卡车按顺序访问地点,要求求出运输物品为 i i 的时候,去的最大地点标号。
不能跳过任何地点。

题解

易知, 1 3 1、3 物品放一块, 2 4 2、4 放一块。
如果只放同一种不冲突的话,如何求呢?
我们可以发现的是,最大地点标号为 p o s pos 时,显然包含所有 r p o s r \leq pos 的物品。
也就是,我们处理 [ r , n ] + 1 [r,n]+1 即可。
然后访问每个点,就能得到最大标号为该点,可以得到的最大物品数量。

考虑两块交叉放,在上面的基础上,对于每个线段, [ 1 , l ] [1,l] 放另一块,取最值是 t m p tmp ,答案是 t m p + 1 tmp+1 ,对线段树取最值更新即可。
首先左端点按顺序,能保证, [ 1 , l ] [1,l] 一定是已经被更新过的,但是会不会出现,排序后的顺序导致最值本可以更新但没有更新呢?
首先对于 x x 点,当前被尝试更新 M M ,此时值为 P P ,当新的线段加进来,对 M M P P 同时加 1 1 ,大小关系不变,所以不会影响。

最后设置两个标记,取最值标记和加标记。
这题比较适合数组建树,我不太熟,就对着大哥的代码写了。

#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;

const int maxn = 3e5+500;

struct node{
    int l,r,type;
    friend bool operator < (node a,node b){
        return a.l<b.l;
    }
}A[maxn];

struct tree{int max,add,alt;}Tr[maxn<<2][2];
int ans[maxn];

void push_up(int rt,int k){
    Tr[rt][k].max=max(Tr[rt<<1][k].max,Tr[rt<<1|1][k].max);
}

void mark(int rt,int k,int type,int val){
    if(type==1){
        Tr[rt][k].add+=val;
        Tr[rt][k].alt+=val;
        Tr[rt][k].max+=val;
    }
    else{
        Tr[rt][k].max=max(Tr[rt][k].max,val);
        Tr[rt][k].alt=max(Tr[rt][k].alt,val);
    }
}

void push_down(int rt,int k){
    if(Tr[rt][k].add>0){
        mark(rt<<1,k,1,Tr[rt][k].add);
        mark(rt<<1|1,k,1,Tr[rt][k].add);
        Tr[rt][k].add=0;
    }
    if(Tr[rt][k].alt>0){
        mark(rt<<1,k,2,Tr[rt][k].alt);
        mark(rt<<1|1,k,2,Tr[rt][k].alt);
        Tr[rt][k].alt=0;
    }
}

void update(int rt,int l,int r,int x,int y,int k,int val,int id){
    if(x<=l&&r<=y){
        mark(rt,k,id,val);
        return ;
    }
    push_down(rt,k);
    int mid=(l+r)>>1;
    if(x<=mid)update(rt<<1,l,mid,x,y,k,val,id);
    if(y>mid)update(rt<<1|1,mid+1,r,x,y,k,val,id);
    push_up(rt,k);
}

int query(int rt,int l,int r,int pos,int k){
    if(l==r)return Tr[rt][k].max;
    push_down(rt,k);
    int mid=(l+r)>>1;
    if(pos<=mid)return query(rt<<1,l,mid,pos,k);
    else return query(rt<<1|1,mid+1,r,pos,k);
}

int main(){
    int n,m,T;cin>>T;
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<=4*n;i++)Tr[i][0].add=Tr[i][0].alt=Tr[i][0].max=0;
        for(int i=0;i<=4*n;i++)Tr[i][1].add=Tr[i][1].alt=Tr[i][1].max=0;
        for(int i=1;i<=m;i++){
            char str[2];scanf("%s",str);
            if(str[0]=='E'||str[0]=='C')A[i].type=0;
            else A[i].type=1;
        }
        for(int i=1;i<=m;i++)scanf("%d",&A[i].l);
        for(int i=1;i<=m;i++)scanf("%d",&A[i].r);
        sort(A+1,A+1+m);
        for(int i=1;i<=m;i++){
            if(A[i].l>A[i].r)continue;
            update(1,1,n,A[i].r,n,A[i].type,1,1);
            int tmp=query(1,1,n,A[i].l,1-A[i].type)+1;
            update(1,1,n,A[i].r,n,A[i].type,tmp,2);
        }
        for(int i=1;i<=m;i++)ans[i]=inf;
        for(int pos=n;pos>=1;pos--){
            int t1=query(1,1,n,pos,0);
            int t2=query(1,1,n,pos,1);
            ans[t1]=ans[t2]=pos;
        }
        for(int i=m-1;i>=1;i--)ans[i]=min(ans[i],ans[i+1]);
        for(int i=1;i<=m;i++)printf("%d ",ans[i]==inf?-1:ans[i]);
        putchar('\n');
    }
}

发布了203 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/mxYlulu/article/details/104615561