题目:
请看原题题面
题解:
可以发现每个组所占的房间的间隔永远是一样的,所以房间位置就是一个等差数列,我们维护每个组的最左端的房间位置 s t a r t start start和间隔 s t e p step step,具体的是用两棵线段树分别维护 s t a r t start start和 s t e p step step,那么操作1和操作2就变成了带有乘法和加法标记的线段树的操作了。对于操作3另外考虑,我们把连续的来有限个客人的情况所在一起,那么对于操作3的 x x x可以通过回溯来客人的影响得到答案,来无限个客人会使 x x x除以2,对于有限个客人由于连续的情况我们缩在一起考虑,所以要么全部回溯,要么答案就在这个连续段内,那么我们预处理出这一段的前缀和,二分即可,所以操作3的复杂度是 l o g log log的。
复杂度: O ( q l o g x ) O(qlogx) O(qlogx)
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<sstream>
#include<ctime>
//#include<chrono>
//#include<random>
//#include<unordered_map>
using namespace std;
#define ll long long
#define ls o<<1
#define rs o<<1|1
#define pii pair<int,ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int maxn=3e5+5;
ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int q,cnt=0,tp,lst,tot,fp,ers[maxn];
vector<pii>fi[maxn];
int inf[maxn];
struct SegTree{
struct node{
int l,r;
ll v,add,mul;
}t[maxn<<2];
void build(int o,int l,int r){
t[o].l=l;t[o].r=r;t[o].add=0;t[o].mul=1;t[o].v=0;
if(l==r)return;
int m=(l+r)>>1;
build(ls,l,m);
build(rs,m+1,r);
}
void pushup(int o){
t[o].v=(t[ls].v+t[rs].v)%mod;
}
void pushdown(int o){
if(t[o].mul!=1){
t[ls].add=t[ls].add*t[o].mul%mod;
t[ls].mul=t[ls].mul*t[o].mul%mod;
t[ls].v=t[ls].v*t[o].mul%mod;
t[rs].add=t[rs].add*t[o].mul%mod;
t[rs].mul=t[rs].mul*t[o].mul%mod;
t[rs].v=t[rs].v*t[o].mul%mod;
t[o].mul=1;
}
if(t[o].add){
t[ls].add=(t[ls].add+t[o].add)%mod;
t[ls].v=(t[ls].v+t[o].add*(t[ls].r-t[ls].l+1)%mod)%mod;
t[rs].add=(t[rs].add+t[o].add)%mod;
t[rs].v=(t[rs].v+t[o].add*(t[rs].r-t[rs].l+1)%mod)%mod;
t[o].add=0;
}
}
void upd_add(int o,int ql,int qr,int k){
if(ql<=t[o].l&&t[o].r<=qr){
t[o].add=(t[o].add+k)%mod;
t[o].v=(t[o].v+k*(t[o].r-t[o].l+1)%mod)%mod;
return;
}
pushdown(o);
int m=(t[o].l+t[o].r)>>1;
if(ql<=m)upd_add(ls,ql,qr,k);
if(qr>m)upd_add(rs,ql,qr,k);
pushup(o);
}
void upd_mul(int o,int ql,int qr){
if(ql<=t[o].l&&t[o].r<=qr){
t[o].mul=t[o].mul*2%mod;
t[o].add=t[o].add*2%mod;
t[o].v=t[o].v*2%mod;
return;
}
pushdown(o);
int m=(t[o].l+t[o].r)>>1;
if(ql<=m)upd_mul(ls,ql,qr);
if(qr>m)upd_mul(rs,ql,qr);
pushup(o);
}
void upd(int o,int p,int v){
if(t[o].l==t[o].r){
t[o].v=v;
return;
}
pushdown(o);
int m=(t[o].l+t[o].r)>>1;
if(p<=m)upd(ls,p,v);
else upd(rs,p,v);
pushup(o);
}
ll qry(int o,int p){
if(t[o].l==t[o].r){
return t[o].v;
}
pushdown(o);
int m=(t[o].l+t[o].r)>>1;
if(p<=m)return qry(ls,p);
else return qry(rs,p);
}
}start,step;
int main(void){
// freopen("in.txt","r",stdin);
q=read();
cnt=1;tp=0;tot=0;fp=0;
start.build(1,1,q);
step.build(1,1,q);
start.upd(1,1,0);
step.upd(1,1,1);
int op,k,g,x;
inf[++tp]=1;
lst=0;
int et=0;
while(q--){
op=read();
if(op==1){
k=read();
if(k){
start.upd_add(1,1,cnt,k);
++cnt;
start.upd(1,cnt,0);
step.upd(1,cnt,1);
if(lst){
fi[fp].pb(mp(k,fi[fp].back().se+k));
}
else{
++fp;
fi[fp].pb(mp(k,k));
}
lst=1;
et=0;
}
else{
start.upd_mul(1,1,cnt);
step.upd_mul(1,1,cnt);
++cnt;
start.upd(1,cnt,1);
step.upd(1,cnt,2);
inf[++tp]=cnt;
lst=0;
if(!et){
ers[tp]=cnt;
et=cnt;
}
else{
ers[tp]=et;
}
}
}
else if(op==2){
g=read();x=read();
++g;
ll s=start.qry(1,g);
ll p=step.qry(1,g);
printf("%lld\n",(s+p*(x-1)%mod)%mod);
}
else{
ll x=read();
int ttp=tp,ffp=fp,flag,cur=cnt+1;
if(lst){
flag=1;
}
else{
flag=0;
}
while(1){
if(flag){
if(x>=fi[ffp].back().se){
x-=fi[ffp].back().se;
--ffp;
flag=0;
}
else{
int l=0,r=sz(fi[ffp])-1,ans;
ll sum=fi[ffp].back().se;
while(l<=r){
int m=(l+r)>>1;
if(sum-fi[ffp][m].se<=x){
ans=m;
r=m-1;
}
else{
l=m+1;
}
}
ans=cur-(sz(fi[ffp])-ans);
printf("%d\n",ans-1);
break;
}
}
else{
if(ttp==1){
puts("0");
break;
}
if(x==0){
printf("%d\n",max(ers[ttp]-1,1)-1);
break;
}
if(x%2){
printf("%d\n",inf[ttp]-1);
break;
}
else{
cur=inf[ttp];
x/=2;
--ttp;
if(inf[ttp]+1!=inf[ttp+1]){
flag=1;
}
}
}
}
}
}
return 0;
}