题意
四种物品,
个,每个有自己的起点和终点,相邻物品不能放一起。
卡车按顺序访问地点,要求求出运输物品为
的时候,去的最大地点标号。
不能跳过任何地点。
题解
易知,
物品放一块,
放一块。
如果只放同一种不冲突的话,如何求呢?
我们可以发现的是,最大地点标号为
时,显然包含所有
的物品。
也就是,我们处理
即可。
然后访问每个点,就能得到最大标号为该点,可以得到的最大物品数量。
考虑两块交叉放,在上面的基础上,对于每个线段,
放另一块,取最值是
,答案是
,对线段树取最值更新即可。
首先左端点按顺序,能保证,
一定是已经被更新过的,但是会不会出现,排序后的顺序导致最值本可以更新但没有更新呢?
首先对于
点,当前被尝试更新
,此时值为
,当新的线段加进来,对
和
同时加
,大小关系不变,所以不会影响。
最后设置两个标记,取最值标记和加标记。
这题比较适合数组建树,我不太熟,就对着大哥的代码写了。
#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');
}
}