P5524 [Ynoi2012] NOIP2015 充满了希望 做题记录

P5524 [Ynoi2012] NOIP2015 充满了希望

Description

给一个长为 \(n\) 的序列,有 \(m\) 个操作,操作编号从 \(1\)\(m\),每个操作为:

1 x y:将序列位置为 \(x,y\) 的两个元素交换。

2 l r x:将序列区间 \([l,r]\) 内所有元素修改为 \(x\)

3 x:查询序列 \(x\) 位置的值。

现在有 \(q\) 次查询,每次查询给出一个操作的区间 \([l,r]\)

先将序列中的元素全部置为 \(0\),之后依次进行从 \(l\)\(r\) 的所有操作,求出所有这些操作中所有 \(3\) 操作的答案的和。

查询之间独立。

\(1\le n,m,q\le 10^6\)\(1\le x\le 10^9\)

Solution

Subtask 3:没有 2 操作

操作中只有交换和查询,可以发现在任意时刻的任意位置都没有值,直接输出 \(0\)

Subtask 4:没有 1 操作

操作中只有区间赋值和查询。

可以发现,在某一个时刻 \(a_x\) 的值,只受到上一次覆盖到它的区间赋值操作的影响。

我们在每一个时刻,对每一个位置都维护出一个 \(t_x\),表示这个位置上一次覆盖到它的操作的编号。

如果一个编号为 \(i\)\(3\) 操作要对一个询问 \(l,r\) 造成贡献,那么需要满足 \(l\in[1,t_x],r\in[i,m]\)

转化为二维偏序问题,将 \(l\) 作为 \(x\) 轴,将 \(r\) 作为 \(y\) 轴,扫描线+树状数组维护答案,线段树维护 \(t_x\)

Overall

仍然用线段树维护 \(t_x\)。对于 2 操作,对应着区间推平;对于 1 操作,对应单点修改。

剩下的和 Subtask 4 一样的做法。

int n,m,Q,k;
int val[N];

struct Segtr{
	int val,cov;
	bool tag;
}tr[N<<2];

struct SegTree{
	void Spread(int p){
		if(!tr[p].tag) return;
		tr[p<<1].val=tr[p<<1|1].val=tr[p].cov;
		tr[p<<1].cov=tr[p<<1|1].cov=tr[p].cov;
		tr[p<<1].tag=tr[p<<1|1].tag=1;
		tr[p].cov=0,tr[p].tag=0;
	}
	
	void Cover(int p,int l,int r,int L,int R,int v){
		if(L<=l&&r<=R){
			tr[p].val=v;
			tr[p].tag=1,tr[p].cov=v;
			return;
		}
		int mid=(l+r)>>1; Spread(p);
		if(L<=mid) Cover(p<<1,l,mid,L,R,v);
		if(R>mid) Cover(p<<1|1,mid+1,r,L,R,v);
	}
	
	void Update(int p,int l,int r,int x,int v){
		if(l==r){
			tr[p].val=v;
			return;
		}
		int mid=(l+r)>>1; Spread(p);
		if(x<=mid) Update(p<<1,l,mid,x,v);
		else Update(p<<1|1,mid+1,r,x,v);
	}
	
	int Ask(int p,int l,int r,int x){
		if(l==r) return tr[p].val;
		int mid=(l+r)>>1; Spread(p);
		if(x<=mid) return Ask(p<<1,l,mid,x);
		else return Ask(p<<1|1,mid+1,r,x);
	}
}Seg;

struct Point{
	int x,y,v,id;
	bool operator<(const Point& tmp)const{
		if(x!=tmp.x) return x<tmp.x;
		else if(y!=tmp.y) return y<tmp.y;
		else return id<tmp.id;
	}
}c[N<<2];

struct Fenwick{
	ll tr[N];
	
	void Update(int x,int v){
		for(;x<=m;x+=x&-x) tr[x]+=v;
	}
	
	ll Ask(int x){
		ll res=0;
		for(;x;x-=x&-x) res+=tr[x];
		return res;
	}
}Bit;

ll ans[N];

signed main(){
	read(n),read(m),read(Q);
	for(int i=1;i<=m;i++){
		int op,l,r;
		read(op);
		if(op==1){
			read(l),read(r);
			int px=Seg.Ask(1,1,n,l);
			int py=Seg.Ask(1,1,n,r);
			Seg.Update(1,1,n,l,py);
			Seg.Update(1,1,n,r,px);
		}
		else if(op==2){
			read(l),read(r),read(val[i]);
			Seg.Cover(1,1,n,l,r,i);
		}
		else{
			int x; read(x);
			int p=Seg.Ask(1,1,n,x);
			if(!val[p]) continue;
			c[++k]={1,i,val[p],0};
			c[++k]={p+1,i,-val[p],0};
		}
	}
	for(int i=1;i<=Q;i++){
		int l,r; read(l),read(r);
		c[++k]={l,r,0,i};
	}
	sort(c+1,c+k+1);
	for(int i=1;i<=k;i++){
		if(c[i].id==0)
			Bit.Update(c[i].y,c[i].v);
		else ans[c[i].id]=Bit.Ask(c[i].y);
	}
	for(int i=1;i<=Q;i++) printf("%lld\n",ans[i]);
    return 0;
}
posted @ 2025-03-20 18:36  XP3301_Pipi  阅读(21)  评论(0)    收藏  举报
Title