问题 G: 鸽子 (gu)-------------------------思维(二维树状数组)

题目描述
一共有n个人依次走进机房,第i个人的实力为ai。

第i个人在走进机房时,会膜拜当前已经在机房里的人x,当且仅当ax>ai。

同理,第i个人在走进机房时,会被当前已经在机房里的人x膜拜,当且仅当ax<ai。

第i个人的音量为vi。设他在走进机房的时候,膜拜了k个人,那么,他会产生vi×k的噪音值。

假设他走进机房时,膜拜他的人的集合为{s1,s2,s3,…,sm},那么这些人会产生***的噪音值。

ctt2006巨佬想知道,每个人走进机房时,当前总共会产生多少噪音值。由于他忙着吊打集训队,于是把问题交给
输入
第一行一个正整数n,表示人数。
接下来n行,每行两个数ai,vi,意义见题目描述。
输出
一行n个数,以空格分隔。第i个数表示第i个人走进机房时(包括之前)产生的噪音。
由于这些值可能很大,只要输出它们mod 998244353的值即可。
样例输入 Copy
5
3 1
2 3
1 4
5 2
4 5
样例输出 Copy
0 3 11 19 32
提示
样例1解释:
第一个人走进机房,由于只有一个人,噪音为0;
第二个人走进机房,比他强的有1,没有比他弱的人,当前总共产生:3×1=3噪音;
第三个人走进机房,比他强的有1,2,没有比他弱的人,当前总共产生:3×1+4×2=11噪音;
第四个人走进机房,没有比他强的人,比他弱的人有1,2,3,当前总共产生:3×1+4×2+1+3+4=19噪音;
第五个人走进机房,比他强的有4,比他弱的有1,2,3,当前总共产生:3×1+4×2+1+3+4+1+3+4+5=19噪音。

解析:

由题意可知,每个人进入机房都需要维护两个值,
一个是膜拜第i个人的噪音总和
一个是第i个人膜拜机房大佬的总和
对于第一个值,我们只要二维树状数组维护即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=998244353;
const int N=5e5+10000;
ll c[N][2];
ll a[N],b[N],num[N];
ll sum[N];
int n;
int lowbit(int x)
{
	return x&(-x);
}
void add(int i,int val,int u)
{
	while(i<N)
	{
		c[i][u]=(c[i][u]+val)%MOD;
		i+=lowbit(i);
	}
}
ll ask(int i,int u)
{
	ll res=0;
	while(i)
	{
		res=(res+c[i][u])%MOD;
		i-=lowbit(i);
	}
	return res;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lld %lld",&a[i],&b[i]),num[i]=a[i];
	sort(num+1,num+1+n);
	int m=unique(num+1,num+1+n)-num;
	for(int i=1;i<=n;i++)
	{
		int k=lower_bound(num+1,num+1+m,a[i])-num;
		//cout<<k<<endl;
		add(k,1,1);add(k,b[i],2);
		
		ll val=ask(k-1,2);
	
		val=(val+(ask(N-1,1)-ask(k,1))*b[i]%MOD)%MOD;
		sum[i]=val;
	}
	for(int i=1;i<=n;i++)
	{
		sum[i]=(sum[i-1]+sum[i])%MOD;
		cout<<sum[i]%MOD<<" ";
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值