题目链接:https://www.luogu.com.cn/problem/P3332
思路:我们区间修改用一个线段树维护就可以了。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mid (l+r>>1)
LL a[200000+10], sum[50000*4+10], laz[50000*4+10], rec[50000*4+10];
void BT(LL i, LL l, LL r){
sum[i]=laz[i]=rec[i]=0;
if(l==r){
sum[i]=a[l];
return ;
}
BT(i<<1, l, mid); BT((i<<1)+1, mid+1, r);
sum[i]=sum[i<<1]+sum[(i<<1)+1];
}
void pushdown(LL i, LL l, LL r){
if(rec[i]){//清空线段树
rec[i]=0;
laz[i<<1]=laz[(i<<1)+1]=sum[i<<1]=sum[(i<<1)+1]=0;
rec[(i<<1)]=rec[(i<<1)+1]=1;
}
if(laz[i]){
laz[(i<<1)]+=laz[i]; laz[(i<<1)+1]+=laz[i];
sum[(i<<1)]+=laz[i]*(mid-l+1);
sum[(i<<1)+1]+=laz[i]*(r-mid);
laz[i]=0;
}
}
void add(LL i, LL l, LL r, LL L, LL R, LL v){
if(l==L&&r==R){
laz[i]+=v;
sum[i]+=v*(r-l+1);
return ;
}
if(laz[i]||rec[i]) pushdown(i, l, r);
if(R<=mid) add(i<<1, l, mid, L, R, v);
else if(L>mid) add((i<<1)+1, mid+1, r, L, R, v);
else add(i<<1, l, mid, L, mid, v), add((i<<1)+1, mid+1, r, mid+1, R, v);
sum[i]=sum[i<<1]+sum[(i<<1)+1];
}
LL query(LL i, LL l, LL r, LL L, LL R){
if(l==L&&r==R){
return sum[i];
}
if(laz[i]||rec[i]) pushdown(i, l, r);
if(R<=mid) return query(i<<1, l, mid, L, R);
if(L>mid) return query((i<<1)+1, mid+1, r, L, R);
return query(i<<1, l, mid, L, mid)+query((i<<1)+1, mid+1, r, mid+1, R);
}
struct node{
LL x, y, type, l, r, k, id;
//值 添加/删除 查询/修改 区间 第k大 询问数
}q[100000+5], q1[100000+5], q2[100000+5];
LL tot, totx, n, m, ans[100000+5];
void solve(LL ql, LL qr, LL l, LL r){
if(ql>qr) return ;
if(l==r){
for(LL i=ql; i<=qr; i++){
if(q[i].type==2){
ans[q[i].id]=l;
}
}
return ;
}
rec[1]=1, laz[1]=sum[1]=0;//清空线段树
LL t1=0, t2=0;
for(LL i=ql; i<=qr; i++){
if(q[i].type==1){
if(q[i].x>mid){//第k大
add(1, 1, n, q[i].l, q[i].r, q[i].y);
q2[t2++]=q[i];
}
else{
q1[t1++]=q[i];
}
}
else{
LL tt=query(1, 1, n, q[i].l, q[i].r);
if(tt<q[i].k){
q[i].k-=tt;
q1[t1++]=q[i];
}
else{
q2[t2++]=q[i];
}
}
}
for(LL i=0; i<t1; i++) q[ql+i]=q1[i];
for(LL i=0; i<t2; i++) q[ql+t1+i]=q2[i];
solve(ql, ql+t1-1, l, mid);
solve(ql+t1, qr, mid+1, r);
}
int main(){
tot=0, totx=0;
scanf("%lld%lld", &n, &m);
BT(1, 1, n);
LL k, x, y, v;
for(LL i=1; i<=m; i++){
scanf("%lld%lld%lld%lld", &k, &x, &y, &v);
if(k==1){
q[++tot].x=v, q[tot].y=1, q[tot].type=1, q[tot].l=x, q[tot].r=y;
}
else{
q[++tot].type=2, q[tot].k=v, q[tot].l=x, q[tot].r=y, q[tot].id=++totx;
}
}
solve(1, m, -n, n);
for(LL i=1; i<=totx; i++){
printf("%lld\n", ans[i]);
}
return 0;
}