E. Painting the Fence(线段树)
思路:线段树的区间修改+单点询问。
考虑:将 标记和 用一个变量 表示,因为初始化 本身就是一种修改。
然后就是用双端队列维护每个颜色对应的区间,每次修改的时候,找到一个满足条件的区间修改即可。
不过貌似应该有更优的方法。
#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;
}