离散化线段树

[题目链接] (https://ac.nowcoder.com/acm/contest/887/E)
题解:这题如果不卡空间的话,那么直接动态开点的水题,如果卡空间,离散化一下,在建线段树,再lz更新一下,注意离散化后与原来的数据的操作是有差距。

#include<bits/stdc++.h>
#define m (l+r)/2
#define ls o*2
#define rs o*2+1
#define ll long long
using namespace std;
const int maxn = 8e5+10;
ll x1[maxn],x2[maxn];
int s[maxn],l[maxn],r[maxn];
ll tr[maxn*4],lz[maxn*4];
int n,sz = 0;
void push(int o,int l,int r)
{
	if(lz[o]){
	 tr[rs] += lz[o] * (s[r]-s[m]) ;
	 tr[ls] += lz[o] * (s[m]-s[l-1]);
	 lz[ls] += lz[o] ; lz[rs] += lz[o];
	 lz[o] = 0; 
	} 
}
void up(int o,int l,int r,int ql,int qr)
{
	if(ql<=l&&qr>=r)
	{
		tr[o] += s[r] - s[l-1];
		lz[o]++;
		return ;
	}
	push(o,l,r);
	if(ql<=m) up(ls,l,m,ql,qr);
	if(qr>m) up(rs,m+1,r,ql,qr);
	tr[o] = tr[ls] + tr[rs];
}
int qu(int o,int l,int r,ll k)
{
	if(l==r)
	{
		int tmp = tr[o] / (s[r]-s[l-1]);
		return (k+tmp-1)/tmp + s[l-1];
	}
	push(o,l,r);
	if(k>tr[ls]) return qu(rs,m+1,r,k-tr[ls]);
	else return qu(ls,l,m,k);
}
void init()
{
	cin >> n;
	ll a1,b1,c1,m1,a2,b2,c2,m2;
    cin>>x1[1]>>x1[2]>>a1>>b1>>c1>>m1>>x2[1]>>x2[2]>>a2>>b2>>c2>>m2;
    for(int i=1;i<=n;i++)
    {
    	if(i>2){
    		x1[i] = (a1*x1[i-1]+b1*x1[i-2]+c1)%m1;
    		x2[i] = (a2*x2[i-1]+b2*x2[i-2]+c2)%m2;
		}
		l[i] = min(x1[i],x2[i]) ;
		r[i] = max(x1[i],x2[i]) + 1;
		s[++sz] = l[i];
		s[++sz] = r[i];
	}
	sort(s+1,s+1+sz);
	sz = unique(s+1,s+1+sz) - s - 1;
}
int main()
{
	init();
	for(int i=1;i<=n;i++){
		l[i] = lower_bound(s+1,s+1+sz,l[i]) - s;
		r[i] = lower_bound(s+1,s+1+sz,r[i]) - s;
		up(1,1,sz,l[i]+1,r[i]);
		ll k = tr[1] / 2;
		if(tr[1]&1) k++;
		printf("%d\n",qu(1,1,sz,k));
	}
}

注意的是:假如我要更新离散化后的(1,4),那么我实际更新的是(2,4),这样保证叶子节点都有值,且我查询的时候能够方便,但是查询的时候需要注意tmp算的是每个数的高度,因为我一开始计算的时候已经将l[i]减去1了,那么我接下来查到这个节点时只要k有值,结果就需要+1,这就是向上取整的原因。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值