[bzoj3110] [Zjoi2013]K大數查詢
阿新 • • 發佈:2018-12-20
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; }