【无标题】

本文介绍了一段C++代码,使用线段树数据结构解决区间修改和查询问题,主要涉及数组操作、线段树构建、修改和查询函数以及在给定数组中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

#include <bits/stdc++.h>
// #define int long long
using namespace std;
#define ls u<<1
#define rs u<<1|1

const int N = 200010;
int pre[N];
int nxt[N];
int st[N];
int a[N];
int X[N];
struct line{
	int x1,x2,y;
	int tag;
	bool operator<(line &t){return y<t.y;}
}L[N];
struct tree{
	int l,r;
	int cnt,len;
}tr[N*8];
void pushup(int u){
	int l = tr[u].l, r = tr[u].r;
	if(tr[u].cnt) tr[u].len = X[r+1] - X[l];//向右偏移
	else tr[u].len = tr[ls].len + tr[rs].len;
}
void build(int u,int l,int r){
	tr[u]={l,r,0,0};
	if(l==r) return;
	int mid = (l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
}
void modify(int u,int l,int r,int tag){
	if(l>tr[u].r||r<tr[u].l) return;
	if(l<=tr[u].l&&r>=tr[u].r){
		tr[u].cnt+=tag;
		pushup(u);
		return;
	}

	modify(ls,l,r,tag);
	modify(rs,l,r,tag);
	pushup(u);
}
signed main(){
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(st[a[i]]==0){
			pre[i]=0;
			st[a[i]]=i;
		}else{
			pre[i]=st[a[i]];
			nxt[pre[i]] = i;
			st[a[i]]=i;
		}
	}
	for(int i=1;i<=n;i++){
		if(nxt[i]==0){
			nxt[i]=n+1;
		}
	}
	for(int i=1;i<=n;i++){
		L[i]={pre[i]+1,i,i-1,1};
		L[i+n]={pre[i]+1,i,nxt[i]-1,-1};
		X[i]=pre[i],X[i+n]=i;
	}
	n = 2 * n;
	sort(L+1,L+1+n);
	sort(X+1,X+1+n);
	int s = unique(X+1,X+1+n)-X - 1;
	build(1,1,s-1);

	long long ans = 0;

	for(int i=1;i<n;i++){
		int l = lower_bound(X+1,X+1+s,L[i].x1)-X;
		int r = lower_bound(X+1,X+1+s,L[i].x2)-X;
		modify(1,l,r-1,L[i].tag);//传参向左偏移
		ans = ans + 1ll*tr[1].len*(L[i+1].y-L[i].y);
	}
	cout<<ans<<'\n';
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值