[题目链接] (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,这就是向上取整的原因。