题目大意就是区间push_back一个数字,求区间不严格第K大之类的,强制在线。然后你直接像区间加区间求和的BIT那样差分后维护自己和自己乘以下标即可, O ( m lg 2 n ) O(m\lg^2n) O(mlg2n)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define lint long long
#define gc getchar()
#define lb(x) ((x)&(-(x)))
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define N 200010
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
const int mxa=1000010;int n,m;
inline int inn() { int x,ch; while((ch=gc)<'0'||ch>'9');x=ch^'0';while((ch=gc)>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0');return x; }
inline lint inln(){lint x,ch;while((ch=gc)<'0'||ch>'9');x=ch^'0';while((ch=gc)>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0');return x; }
struct segment{
lint s;segment *ch[2];
}*A[N],*B[N],*tmp,*ansT[N],*savT[N];
int sgn[N],ansc;lint sa[N],sb[N];
int build(segment* &rt,int l,int r)
{
rt=new segment,rt->s=0;if(l==r) return 0;int mid=(l+r)>>1;
return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r),0;
}
int update(segment* &y,segment* &x,int p,lint v,int l=1,int r=mxa)
{
x=new segment,x->s=y->s+v,x->ch[0]=y->ch[0],x->ch[1]=y->ch[1];
if(l==r) return 0;int mid=(l+r)>>1;
if(p<=mid) update(y->ch[0],x->ch[0],p,v,l,mid);
else update(y->ch[1],x->ch[1],p,v,mid+1,r);return 0;
}
lint query(segment* &rt,int s,int t,int l=1,int r=mxa)
{
if(s<=l&&r<=t) return rt->s;lint ans=0;int mid=(l+r)>>1;
if(s<=mid) ans+=query(rt->ch[0],s,t,l,mid);
if(mid<t) ans+=query(rt->ch[1],s,t,mid+1,r);return ans;
}
inline segment* upd(segment* &rt,int p,lint v) { return update(rt,tmp,p+1,v),tmp; }
inline int upd(int x,int p,int v)
{
if(x<=0||x>n) return 0;int va=v,vb=v*x;
for(;x<=n;x+=lb(x)) A[x]=upd(A[x],p,va),B[x]=upd(B[x],p,vb);
return 0;
}
inline int _query(int x,int va,int vb)
{
if(x<=0||x>n) return 0;
for(;x;x-=lb(x)) ansT[++ansc]=A[x],sgn[ansc]=va,(vb?ansT[++ansc]=B[x],sgn[ansc]=vb:0);
return 0;
}
inline int qry(int s,int t,int v) { return _query(t,v,-1),_query(s-1,-v,1),_query(s-1,t-s+1,0); }
int main()
{
n=inn(),m=inn(),build(A[0],1,mxa),B[0]=A[0];rep(i,1,n) inn(),A[i]=A[0],B[i]=B[0];
// int x;rep(i,1,n) x=(inn()>0),sa[i]=sa[i-1]+x,sb[i]=sb[i-1]+x*i;
// rep(i,1,n) A[i]=upd(A[0],0,sa[i]-sa[i-lb(i)]),B[i]=upd(B[0],0,sb[i]-sb[i-lb(i)]);//,debug(i)sp,debug(A[i]->s)sp,debug(B[i]->s)ln;
for(int lasp=0;m;m--)
{
int opt=inn(),l=inn(),r=inn(),a;lint s;
if(!opt) a=inn()^lasp,(a?upd(l,a,1),upd(r+1,a,-1):0);
else{
s=inln(),ansc=0,qry(l,r,r+1),l=1,r=mxa;
lint ts=0;rep(i,1,ansc) ts+=sgn[i]*ansT[i]->s;
if(ts<=s) { printf("%d %lld\n",lasp=1,ts);continue; }
s++;rep(i,1,ansc) savT[i]=ansT[i];lint anss=0;
while(l<r)
{
int mid=(l+r)>>1;ts=0;
rep(i,1,ansc) ts+=sgn[i]*ansT[i]->ch[1]->s;
if(s>ts) { s-=ts;rep(i,1,ansc) ansT[i]=ansT[i]->ch[0];r=mid,anss+=ts; }
else { rep(i,1,ansc) ansT[i]=ansT[i]->ch[1];l=mid+1; }
}
printf("%d %lld\n",lasp=l,anss);
}
// rep(i,1,n) debug(i)sp,debug(A[i]->s)sp,debug(B[i]->s)ln;
}
return 0;
}