1. 程式人生 > >[BZOJ3110][ZJOI2013]K大數查詢

[BZOJ3110][ZJOI2013]K大數查詢

div gin 代碼 class clu getchar() mar 一行 zoj

BZOJ
Luogu
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
HINT
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N

2操作中c<=Maxlongint

sol

樹套樹題解
線段樹套線段樹,註意內層是動態開節點。
先確定內外層關系:外層表示數值,內層表示區間。(你可以試一試反過來)
那麽修改操作就是外層的單點修改,而實際上應該是單點到根的路徑上的節點的修改,即我們要修改log棵線段樹。在每個線段樹裏面是區間加1。可以直接寫標記永久化(練一波手)
查詢時在外層二分,就是常規的求第k大,只是每次算右兒子size的時候都要在右兒子那棵線段樹上查一下區間和。
外層線段樹直接用循環代替
代碼好寫得很

code

#include<cstdio>
#include<algorithm>
using
namespace std; const int N = 50005; #define ll long long struct segment_tree{ int ls,rs,tim;ll num; }t[N*300]; int n,m,rt[N*16],tot; int gi() { int x=0,w=1;char ch=getchar(); while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if (ch=='-') w=0,ch=getchar(); while
(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return w?x:-x; } void Modify(int &x,int l,int r,int ql,int qr) { if (!x) x=++tot; if (l==ql&&r==qr) {t[x].tim++;return;} t[x].num+=qr-ql+1; int mid=l+r>>1; if (qr<=mid) Modify(t[x].ls,l,mid,ql,qr); else if (ql>mid) Modify(t[x].rs,mid+1,r,ql,qr); else Modify(t[x].ls,l,mid,ql,mid),Modify(t[x].rs,mid+1,r,mid+1,qr); } ll Query(int x,int l,int r,int ql,int qr) { ll res=1ll*t[x].tim*(qr-ql+1); if (l==ql&&r==qr) return res+t[x].num; int mid=l+r>>1; if (qr<=mid) return res+Query(t[x].ls,l,mid,ql,qr); else if (ql>mid) return res+Query(t[x].rs,mid+1,r,ql,qr); else return res+Query(t[x].ls,l,mid,ql,mid)+Query(t[x].rs,mid+1,r,mid+1,qr); } int main() { n=gi();m=gi(); while (m--) { int opt=gi(),a=gi(),b=gi(),c=gi(),now=1,l=1,r=n; if (opt==1) while (233) { Modify(rt[now],1,n,a,b); if (l==r) break; int mid=l+r>>1; if (c<=mid) now=now<<1,r=mid; else now=now<<1|1,l=mid+1; } else while (l<r) { ll sum=Query(rt[now<<1|1],1,n,a,b); int mid=l+r>>1; if ((ll)c<=sum) now=now<<1|1,l=mid+1; else c-=sum,now=now<<1,r=mid; } if (opt==2) printf("%d\n",l); } return 0; }

[BZOJ3110][ZJOI2013]K大數查詢