已A,但是不懂
查看原帖
已A,但是不懂
242317
xiaofu15191楼主2024/7/31 16:01

为什么在线段树中 pushup 时,不 pushup 可行的中间点(可作为区间非两边的领队的个数)也能过?

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
long long n,num[200010],where[200010],pre[200010];
struct node
{
	long long l_num,mid_num,sum,lazy;
}tree[800010];
void pushup(long long now)
{
	tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
	tree[now].l_num=tree[now<<1].l_num+tree[now<<1|1].l_num;
	tree[now].mid_num=tree[now<<1].mid_num+tree[now<<1|1].mid_num;
}
void pushdown(long long now)
{
	tree[now<<1].lazy+=tree[now].lazy;
	tree[now<<1].mid_num+=tree[now].lazy;
	tree[now<<1].sum+=tree[now].lazy*tree[now<<1].l_num;
	tree[now<<1|1].lazy+=tree[now].lazy;
	tree[now<<1|1].mid_num+=tree[now].lazy;
	tree[now<<1|1].sum+=tree[now].lazy*tree[now<<1|1].l_num;
	tree[now].lazy=0;
}
void update_l(long long now,long long l,long long r,long long x,long long k)
{
	if(r<x||l>x) return;
	if(l==r)
	{
		tree[now].l_num+=k;
		tree[now].sum=tree[now].l_num*tree[now].mid_num;
		return;
	}
	pushdown(now);
	long long mid=(l+r)>>1;
	if(x<=mid) update_l(now<<1,l,mid,x,k);
	else update_l(now<<1|1,mid+1,r,x,k);
	pushup(now);
}
void update_mid(long long now,long long l,long long r,long long x,long long y,long long k)
{
	if(r<x||l>y) return;
	if(x<=l&&r<=y)
	{
		tree[now].mid_num+=k;
		tree[now].lazy+=k;
		tree[now].sum+=tree[now].l_num*k;
		return;
	}
	pushdown(now);
	long long mid=(l+r)>>1;
	if(x<=mid) update_mid(now<<1,l,mid,x,y,k);
	if(y>mid) update_mid(now<<1|1,mid+1,r,x,y,k);
	pushup(now);
}
long long query(long long now,long long l,long long r,long long x,long long y)
{
	if(r<x||l>y) return 0;
	if(x<=l&&r<=y) return tree[now].sum;
	pushdown(now);
	long long mid=(l+r)>>1,res=0;
	if(x<=mid) res+=query(now<<1,l,mid,x,y);
	if(y>mid) res+=query(now<<1|1,mid+1,r,x,y);
	return res;
}
int main()
{
	scanf("%lld",&n);
	for(long long i=1;i<=n;i++)
	{
		scanf("%lld",&num[i]);
		pre[i]=where[num[i]];
		where[num[i]]=i;
	}
	long long ans=0;
	for(long long i=1;i<=n;i++)
	{
		if(pre[i])
		{
			update_l(1,1,n,pre[i],-1);
			update_mid(1,1,n,pre[pre[i]]+1,pre[i]-1,-1);
		}
		ans+=query(1,1,n,pre[i]+1,i-1);
		update_l(1,1,n,i,1);
		update_mid(1,1,n,pre[i]+1,i-1,1);
	}
	printf("%lld\n",ans);
}

中间的可行点指的就是 node 中的 mid_sum。

2024/7/31 16:01
加载中...