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