[bzoj3110] [Zjoi2013]K大数查询
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M
接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果
Sample Input
2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
1
2
1
solution
树套树,直接外层权值线段树,内层位置线段树就行了。
然后是卡常环节。。
内层由于要涉及到区间加法,用标记永久化,然后少开$long,long \(就\)A$掉了。。
虽然一个月前我T了之后说要卡这题常然后咕了一个月。。
总之还是比较好写的,虽然我在luogu上交T了两版。。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
const int maxn = 2e5+10;
const int N = 1e5;
ll sum[maxn*100];
int ls[maxn*100],rs[maxn*100],tag[maxn*100],tot;
int rt[maxn],n,m,a[maxn],op[maxn],inl[maxn],inr[maxn],inc[maxn];
#define mid ((l+r)>>1)
struct Segment_Tree_1 {
void modify(int &p,int l,int r,int x,int y) {
if(!p) p=++tot;sum[p]+=1ll*(y-x+1);
if(x<=l&&r<=y) return tag[p]++,void();
if(x<=mid) modify(ls[p],l,mid,x,min(y,mid));
if(y>mid) modify(rs[p],mid+1,r,max(x,mid+1),y);
}
ll query(int p,int l,int r,int x,int y,int del=0) {
if(x<=l&&r<=y) return sum[p]+1ll*del*(r-l+1);
int ans=0;
if(x<=mid) ans+=query(ls[p],l,mid,x,min(y,mid),del+tag[p]);
if(y>mid) ans+=query(rs[p],mid+1,r,max(x,mid+1),y,del+tag[p]);
return ans;
}
};
struct Segment_Tree_2 {
Segment_Tree_1 SGT[maxn];
void insert(int p,int l,int r,int x,int y,int c) {
SGT[p].modify(rt[p],1,n,x,y);
if(l==r) return ;
if(c<=mid) insert(p<<1,l,mid,x,y,c);
else insert(p<<1|1,mid+1,r,x,y,c);
}
int kth(int p,int l,int r,int x,int y,ll k) {
if(l==r) return l;
ll sz=SGT[p<<1|1].query(rt[p<<1|1],1,n,x,y);
if(sz>=k) return kth(p<<1|1,mid+1,r,x,y,k);
else return kth(p<<1,l,mid,x,y,k-sz);
}
}SGT;
signed main() {
read(n),read(m);int cnt=0;
for(int i=1;i<=m;i++) {
read(op[i]),read(inl[i]),read(inr[i]),read(inc[i]);
if(op[i]==1) a[++cnt]=inc[i];
}
sort(a+1,a+cnt+1);int M=unique(a+1,a+cnt+1)-a-1;
for(int i=1;i<=m;i++)
if(op[i]==1) inc[i]=lower_bound(a+1,a+M+1,inc[i])-a;
for(int i=1;i<=m;i++)
if(op[i]==1) SGT.insert(1,1,n,inl[i],inr[i],inc[i]);
else write(a[SGT.kth(1,1,n,inl[i],inr[i],inc[i])]);
return 0;
}