BZOJ 3110 Zjoi2013 K大數查詢

2021-07-13 13:48:00 字數 2830 閱讀 8086

title: 『bzoj 3110 [zjoi2013]k大數查詢』

categories: bzoj

date: 2016-2-3 00:00:00

tags: [樹套樹,整體二分]

有n個位置,m個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入乙個數c

如果是2 a b c形式,表示詢問從第a個位置到第b個位置,第c大的數是多少。

第一行n,m

接下來m行,每行形如1 a b c或2 a b c

輸出每個詢問的結果。

input.txt

2 5

1 1 2 1

1 1 2 2

2 1 1 2

2 1 1 1

2 1 2 3

output.txt

1 2

1好久沒更部落格了。。

首先這題乙個位置可以加多個數,一開始沒有看懂題意很坑爹。。。

這樣一來,我們可以對開乙個二維線段樹,外層是權值線段樹,內層是區間線段樹。這樣做的意義是,對每乙個權值的區間都用乙個線段樹來維護其出現的位置和次數。因為樹套樹太耗記憶體了,還是在修改的時候新建節點比較好。。。

在外層那顆線段樹寫類似於二分的非遞迴就好了,因為並不需要用子節點來更新他的資訊。

還有因為我太弱了所以並沒有寫標記永久化……感覺要去學習一下新姿勢了。

感覺一般可以用樹套樹做的題目整體二分也是可以的?權值那層線段樹只需要二分就好了,然後再用乙個線段樹來處理整體二分時候對詢問資訊的處理。

#include

#include

#include

#include

#define maxn (50000+5)

#define maxm (5000000+5)

using namespace std;

struct seg_treetr[maxm<<2];

int root[maxn<<2];

int n,m,cnt;

inline int in()

void update(int ind)

void pushdown(int ind,int l,int r)

tr[ind].tag=0;

}void modify(int &ind,int l,int r,int ql,int qr)

int mid=(l+r)>>1;

if(qr<=mid) modify(tr[ind].lc,l,mid,ql,qr);

else if(ql>mid) modify(tr[ind].rc,mid+1,r,ql,qr);

else modify(tr[ind].lc,l,mid,ql,mid),modify(tr[ind].rc,mid+1,r,mid+1,qr);

update(ind);

}int getsum(int ind,int l,int r,int ql,int qr)

void insert(int a,int b,int c)

modify(root[ind],1,n,a,b);

}int query(int a,int b,int c)

return l;

}int main()

return

0;

}

#include

#include

#include

#include

#include

#define maxn 50000+5

using namespace std;

struct seg_treetr[maxn<<4];

struct queryq[maxn];

int res[maxn];

int n,m;

bool cmp(const query &s,const query &b)

void pushdown(int k)

if(tr[k].tag)

}void build(int l,int r,int k)

void add(int l,int r,int val,int k)

if(r<=tr[k<<1].r) add(l,r,val,k<<1);

else

if(l>=tr[k<<1|1].l) add(l,r,val,k<<1|1);

else add(l,tr[k<<1].r,val,k<<1),add(tr[k<<1|1].l,r,val,k<<1|1);

update(k);

}int getsum(int l,int r,int k)

void solve(int l,int r,int

x,int

y) int mid=(l+r)>>1,pl=0,pr=y-x+1;

tr[1].mem=1; tr[1].tag=tr[1].sz=tr[1].sum=0;

for(int i=x;i<=y;i++)

if(q[i].ct==1)

}else

else

q[i].k=++pr;

}sort(q+x,q+y+1,cmp);

solve(l,mid,x,x+pl-1); solve(mid+1,r,x+pl,y);

}int main()

build(1,n,1);

solve(0,n,1,m);

for(int i=1;i<=m;i++)

if(res[i]) printf("%d\n",res[i]);

return

0;}

BZOJ 3110 Zjoi2013 K大數查詢

title bzoj 3110 zjoi2013 k大數查詢 categories bzoj date 2016 2 3 00 00 00 tags 樹套樹,整體二分 有n個位置,m個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入乙個數c 如果是2 a...

BZOJ3110 Zjoi2013 K大數查詢

整體二分 樹狀陣列 這道題和某題類似 整體二分,每次二分乙個值,因為是求第k大,比二分值大的在 l r 區間 1,詢問就問這個區間的數,如果數量大於k,說明實際答案大於二分值,下放右區間,否則下放左區間,k減去詢問的值 因為後面不會再考慮mid r的值 把區間加操作也按照權值兩邊下放,每次詢問完答案...

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 ...