题目:有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
N<=50000
M<=50000
思路:二分答案,要用到树状数组区间更新
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
//0x3f3f3f3f
const int maxn=5e4+50;
struct Node{
int type,id,a,b;
LL c;
}q[maxn],q1[maxn],q2[maxn];
struct BIT{
int n;
LL bit0[maxn],bit1[maxn];
void init(int _n){
n=_n;
mm(bit0,0);
mm(bit1,0);
}
void add(LL *b,int i,LL val){
for(;i<=n;i+=i&(-i))
b[i]+=val;
}
LL sum(LL *b,int i){
LL ret=0;
for(;i>0;i-=i&(-i))
ret+=b[i];
return ret;
}
void ADD(int l,int r,LL c){
add(bit0,l,-c*(l-1));
add(bit0,r+1,c*r);
add(bit1,l,c);
add(bit1,r+1,-c);
}
LL SUM(int l,int r){
LL ret=sum(bit0,r)-sum(bit0,l-1);
ret+=sum(bit1,r)*r-sum(bit1,l-1)*(l-1);
return ret;
}
}bit;
int ans[maxn],vis[maxn];
int n,m;
void cdq(int L,int R,int l,int r){
if(L>R) return;
if(l==r){
for(int i=L;i<=R;i++)
if(q[i].type==2)
ans[q[i].id]=l;
return;
}
int sz1=0,sz2=0,mid=(l+r)>>1;
for(int i=L;i<=R;i++){
if(q[i].type==1){
if(q[i].c<=mid) q1[sz1++]=q[i];
else{
bit.ADD(q[i].a,q[i].b,1);
q2[sz2++]=q[i];
}
}
else{
LL ret=bit.SUM(q[i].a,q[i].b);
if(ret>=q[i].c){
q2[sz2++]=q[i];
}
else{
q[i].c-=ret;
q1[sz1++]=q[i];
}
}
}
for(int i=0;i<sz2;i++)
if(q2[i].type==1)
bit.ADD(q2[i].a,q2[i].b,-1);
memcpy(q+L,q1,sz1*sizeof(Node));
memcpy(q+L+sz1,q2,sz2*sizeof(Node));
cdq(L,L+sz1-1,l,mid);
cdq(L+sz1,R,mid+1,r);
}
int main(){
// freopen("D:\\input.txt","r",stdin);
// freopen("D:\\output.txt","w",stdout);
while(~scanf("%d%d",&n,&m)){
bit.init(n);
mm(vis,0);
mm(ans,0);
int mi=n,mx=-n;
for(int i=1;i<=m;i++){
scanf("%d%d%d%lld",&q[i].type,&q[i].a,&q[i].b,&q[i].c);
q[i].id=i;
if(q[i].type==2)
vis[i]=1;
else{
mi=min(mi,(int)q[i].c);
mx=max(mx,(int)q[i].c);
}
}
cdq(1,m,mi,mx);
for(int i=1;i<=m;i++)
if(vis[i])
printf("%d\n",ans[i]);
}
return 0;
}