题目描述:
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
题目分析:
二维线段树维护,一维为权值线段树,二维为区间线段树.
题目链接:
Ac 代码:
// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 50010
#define N 20000100
struct node{
int ls,rs;
int adx,sum;
}t[N];
struct ns{
int opt,l,r,x;
};
ns ts[maxn];
int val[maxn];
int n,T,root[4*maxn],tot;
void add(int &o,int l,int r,int d)
{
if(!o) o=++tot;
t[o].sum+=d*((int)r-l+1);
t[o].adx+=d;
}
void pushdown(int o,int l,int r)
{
int mid=(l+r)>>1;
add(t[o].ls,l,mid,t[o].adx);
add(t[o].rs,mid+1,r,t[o].adx);
t[o].adx=0;
}
void update(int o)
{
t[o].sum=t[t[o].ls].sum+t[t[o].rs].sum;
}
void modify2(int &o,int l,int r,int ql,int qr)
{
if (!o) o=++tot;
if (ql<=l&&r<=qr)
{
add(o,l,r,1);
return;
}
pushdown(o,l,r);
int mid=(l+r)>>1;
if (ql<=mid) modify2(t[o].ls,l,mid,ql,qr);
if (mid<qr) modify2(t[o].rs,mid+1,r,ql,qr);
update(o);
}
int ask2(int &o,int l,int r,int ql,int qr)
{
if (!o) return 0;
if (ql<=l&&r<=qr) return t[o].sum;
pushdown(o,l,r);
int mid=(l+r)>>1,ans=0;
if (ql<=mid) ans+=ask2(t[o].ls,l,mid,ql,qr);
if (mid<qr) ans+=ask2(t[o].rs,mid+1,r,ql,qr);
return ans;
}
void modify1(int o,int l,int r,int x,int ql,int qr)
{
//printf("%d %d\n",l,r);
modify2(root[o],1,n,ql,qr);
if (l==r) return;
int mid=(l+r)>>1;
if (x<=mid) modify1((o<<1),l,mid,x,ql,qr);
if (mid<x) modify1((o<<1)|1,mid+1,r,x,ql,qr);
}
int ask1(int o,int l,int r,int c,int ql,int qr)
{
if (l==r) return l;
int num=ask2(root[(o<<1)|1],1,n,ql,qr);
int mid=(l+r)>>1;
if (num>=c) return ask1((o<<1)|1,mid+1,r,c,ql,qr);
else return ask1((o<<1),l,mid,c-num,ql,qr);
}
int main()
{
//freopen("zjoi13_sequence.in","r",stdin);
//freopen("zjoi13_sequence.out","w",stdout);
scanf("%d%d",&n,&T);
int cnt=0;
for(int i=1;i<=T;i++)
{
int op,x,y,c;
scanf("%d%d%d%d",&ts[i].opt,&ts[i].l,&ts[i].r,&ts[i].x);
if(ts[i].opt==1) val[++cnt]=ts[i].x;
}
std::sort(val+1,val+cnt+1);
int t=std::unique(val+1,val+cnt+1)-val-1;
for(int i=1;i<=T;i++)
{
if(ts[i].opt==1)
{
int poi=std::lower_bound(val+1,val+t+1,ts[i].x)-val;
modify1(1,1,t,poi,ts[i].l,ts[i].r);
}
else
printf("%d\n",val[ask1(1,1,t,ts[i].x,ts[i].l,ts[i].r)]);
}
return 0;
}