首页 > 其他分享 >2018牛客多校第五场 F take[树状数组]

2018牛客多校第五场 F take[树状数组]

时间:2023-08-09 17:33:29浏览次数:42  
标签:return int 第五场 ll 多校 牛客 num pair mod

理解题目画了一个二叉树,然后思维定势让我想构建一个有n层的二叉树,然后统计叶子节点。。有点恐怖。

但是正解是考虑每一个箱子对答案的贡献。

图片来自take_baymax520的博客

对于每个箱子,它要发生交换也就是为答案贡献的条件是它当前宝石大小小于它的大小。对于比它小的宝石之前取(pi)或不取(1-pi)都是无所谓的。

而之前比它大的宝石只有不取(1-pi)时,当前宝石才能对答案产生贡献。那么每个宝石的贡献就如上图了。

然后是用的树状数组维护的前缀积。

树状数组应该有两种思路,一种是按照下标排序,另一种是离散化按照大小排序。

如果要按照下标排序的话,我们需要保证比它小的数不能先出现。此时保证查询它的前缀和的时候,比它小的的位置上是1而不是(1-pi)。所以我们建树操作的时候按照宝石大小从大到小排序即可

按照下标排序的树状数组
#include<iostream>
#include<algorithm>
#define lowbit(x) x&(-x)
using namespace std;
typedef long long ll;
const ll mod=998244353;
pair<ll,ll> exgcd(ll a)
{
    ll b=mod;
	pair<ll,ll>x,y;
	x=make_pair(1,0);
	y=make_pair(0,1);
	while(b)
	{
		ll q=a/b;
		x=make_pair(x.first-y.first*q,x.second-y.second*q);
		a%=b;
		swap(a,b);
		swap(x,y);
	}
	return x;
}
ll _inv(int x)
{
	return (exgcd(x).first+mod)%mod;
}
int n;
struct node
{
	ll d,p,num;
}a[100005];
ll tree[100005],__;
void add(int num,ll p)
{
	while(num<=n)
	{
		tree[num]=(tree[num]*p)%mod;
		num+=lowbit(num);
	}
}
ll ask(int num)
{
	ll ans=1;
	while(num)
	{
		ans=(ans*tree[num])%mod;
		num-=lowbit(num);
	}
	return ans;
}
signed main()
{
	__=_inv(100);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		tree[i]=1;
		cin>>a[i].p>>a[i].d;
		a[i].num=i;
		a[i].p=(a[i].p*__)%mod;
	}
    //按照大小排序
	sort(a+1,a+1+n,[](node x,node y)->bool{return x.d>y.d;});
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		ans=(ans+(a[i].p*ask(a[i].num)%mod))%mod;
		add(a[i].num,1-a[i].p+mod);
	}
	cout<<ans;
	return 0;
}

如果按照大小排序的话,我们需要保证坐标比它大的不能提前出现,那么按照坐标排序即可。

代码根据上面的改一改就是,所以推荐上面那个

按照大小排序的树状数组
 #include<iostream>
#include<algorithm>
#define lowbit(x) x&(-x)
using namespace std;
typedef long long ll;
const ll mod=998244353;
pair<ll,ll> exgcd(ll a)
{
    ll b=mod;
	pair<ll,ll>x,y;
	x=make_pair(1,0);
	y=make_pair(0,1);
	while(b)
	{
		ll q=a/b;
		x=make_pair(x.first-y.first*q,x.second-y.second*q);
		a%=b;
		swap(a,b);
		swap(x,y);
	}
	return x;
}
ll _inv(int x)
{
	return (exgcd(x).first+mod)%mod;
}
int n;
struct node
{
	ll d,p,num;
}a[100005];
ll tree[100005],__;
void add(int num,ll p)
{
	while(num<=n)
	{
		tree[num]=(tree[num]*p)%mod;
		num+=lowbit(num);
	}
}
ll ask(int num)
{
	ll ans=1;
	while(num)
	{
		ans=(ans*tree[num])%mod;
		num-=lowbit(num);
	}
	return ans;
}
signed main()
{
	__=_inv(100);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		tree[i]=1;
		cin>>a[i].p>>a[i].d;
		a[i].num=i;
		a[i].p=(a[i].p*__)%mod;
	}
	//离散化
	sort(a+1,a+1+n,[](node x,node y)->bool{return x.d>y.d;});
	for(int i=1;i<=n;i++)
		a[i].d=i;
	//按照坐标排序
	sort(a+1,a+1+n,[](node x,node y)->bool{return x.num<y.num;});
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		ans=(ans+(a[i].p*ask(a[i].d)%mod))%mod;
		add(a[i].d,1-a[i].p+mod);
	}
	cout<<ans;
	return 0;
}

 

标签:return,int,第五场,ll,多校,牛客,num,pair,mod
From: https://www.cnblogs.com/qbning/p/17617480.html

相关文章

  • 杭电多校 2023 杂题题解
    打算只写点有意思的题。D1JEasyproblemI注意到\(x_i\)单增,所以一个数被减到负数之后,所有的操作都会将它减到负数,也就等价于乘\(-1\)再相加。使用一棵线段树维护所有数,将这些数分为两种,一种如上,一种是区间减。最终所有数都会变为需要乘\(-1\)再相加的数,于是只要每次精......
  • 根号分治-2023牛客7 E-Star Wars
      也就是说对于大点和小点我们采用不同的方式维护对于大点来说我们只需要记录它的周围点的总和不需要知道具体的谁链接了它 对于小点我们需要维护它的所有信息他自己链接了哪些点 需要再开一个vector表示自己链接的大点这样大对大或者小对大的时候维护的信息也......
  • 牛客网整数位宽转换
    1、veilog进阶篇VL32非整数倍数据位宽转换24to48描述:实现数据位宽转换电路,实现24bit数据输入转换为128bit数据输出。其中,先到的数据应置于输出的高bit位。valid_in用来指示数据输入data_in的有效性,valid_out用来指示数据输出data_out的有效性;clk是时钟信号;rst_n是异步复位信......
  • 2023第七场牛客多校-We Love Strings
    I-WeLoveStrings_2023牛客暑期多校训练营7题意 做法:根号分治+容斥原理将字符串分为两类:len<=20直接位运算枚举出可能的所有答案,看是否存在符合的len>20采用容斥原理,计算出所有长度为i的字符串中(假设为n个),1个字符串可以表示的(1个元素的交集) ,2个字符串可以表示的......
  • 2023牛客+杭电补题和总结记录(后半)
    前半继续写要被编辑器卡飞了,换个档杭电第六场\(1002.Pair\Sum\and\Perfect\Square\)对于每个位置可以求出该位置的数和哪些位置的数能够组成完全平方数,因为原序列是排列,并且完全平方数个数不多,所以预处理的复杂度不高。(也可以在后续统计过程中处理)处理出点对以后就变成了......
  • 牛客周赛 Round 6
    牛客周赛Round6A-游游的数字圈_牛客周赛Round6(nowcoder.com)枚举即可#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;signedmain(){ios::sync_with_stdio(false);cin.tie(nullptr);strings;cin>>s;intans=0;......
  • 记一场很厉害的牛客多校
    破防场。全是诈骗提。但是很有可以学的东西!\(I.\)给定\(n\)个01?串,?可以替换为0或1。称替换完的串集合为该串的生成串。问所有\(n\)个串的生成串集合的并的大小。长度不同的串分开处理。对于长度\(\le20\)的串,暴力枚举生成串,map去重。对于长度\(>20\)的......
  • 2023年多校联训NOIP层测试2
    T1 斐波那契树题目思路题解做法:可以先把白色边权看成1,黑色边权看成0,求最小生成树和最大生成树,判断这两个值之间是否存在一个斐波那契数。可以证明这中间的值都是可以出现的(参考求恰好k条白边的思路,BZOJ2654)。我的做法:找到最小生成树和最大生成树的值。看它们是否在点击......
  • 2023年多校联训NOIP层测试4+洛谷 8 月月赛 I & RiOI Round 2
    2023年多校联训NOIP层测试4爆零了T1幸运数字\(0pts\)T2密码\(0pts\)没做到,咕了。T3小X和他的朋友们\(0pts\)没做到,咕了。T4树上询问\(0pts\)没做到,咕了。【LGR-150-Div.2】洛谷8月月赛I&RiOIRound2T1luoguP9496「RiOI-2」hacker\(100pts\)......
  • 2023年牛客多校第五场A
    1:题目链接https://ac.nowcoder.com/acm/contest/57359/A题意:给你一个数组,让你找出区间l,r之间满足l≤i<j<k≤r,ai=ak>aj的个数思路1:我们先找出当前位置x小于x的数有多少个例如:9854515158对应:0000102037你会发现假如有i,k,j满足,则个数为......