E. Painting the Fence(线段树)

E. Painting the Fence(线段树)

思路:线段树的区间修改+单点询问。

考虑:将 l a z y lazy 标记和 c o l o r color 用一个变量 c c 表示,因为初始化 c c 本身就是一种修改。

然后就是用双端队列维护每个颜色对应的区间,每次修改的时候,找到一个满足条件的区间修改即可。

不过貌似应该有更优的方法。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
#define pb push_back
struct node{
	int l,r,c,lz;
}a[N<<2];
deque<int>q[N];
void pushdown(int x){
	if(a[x].c){
		a[lx].c=a[rx].c=a[x].c;
		a[x].c=0;
	}
}
void build(int x,int l,int r){
	a[x].l=l,a[x].r=r,a[x].c=0;
	if(l==r){
		scanf("%d",&a[x].c),q[a[x].c].pb(l);
		return;
	}
	int mid=(l+r)>>1;
	build(lx,l,mid);
	build(rx,mid+1,r);
}
void update(int x,int l,int r,int val){
	if(a[x].l>=l&&a[x].r<=r){
		a[x].c=val;
		return;
	}
	pushdown(x);
	int mid=(a[x].l+a[x].r)>>1;
	if(l<=mid) update(lx,l,r,val);
	if(r>mid) update(rx,l,r,val);
}
int query(int x,int p){
	if(a[x].l==a[x].r) return a[x].c;
	int mid=(a[x].l+a[x].r)>>1;
	pushdown(x);
	int ans=0;
	if(p<=mid) return query(lx,p);
	else  return query(rx,p);
	return ans;
}
int main(){
	int n,m;
	scanf("%d",&n);
	build(1,1,n);
	scanf("%d",&m);
	while(m--){
		int x;
		scanf("%d",&x);
		if(q[x].size()<=1) continue;
		int l=q[x].front(),r=q[x].back();
		while(query(1,l)!=x&&!q[x].empty()){
			  q[x].pop_front();
			  if(!q[x].empty()) l=q[x].front();
		}
		while(query(1,r)!=x&&!q[x].empty()){
			  q[x].pop_back();
			  if(!q[x].empty()) r=q[x].back();
		}
		if(q[x].size()>1) update(1,l,r,x);
	}
	for(int i=1;i<=n;i++)
		printf("%d ",query(1,i));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107517429