(題目鏈結)
有n個位置,m個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入乙個數c;如果是2 a b c形式,表示詢問從第a個位置到第b個位置,第c大的數是多少。
整體二分入門題。
對於一段操作,我們二分乙個答案mid,將修改操作中加入的數c大於等於mid的操作執行(用樹狀陣列維護一段區間中大於等於mid的數的個數)。然後對於詢問判斷c是否大於等於已經加入的大於等於mid的數的個數,然後不斷遞迴下去。
第k大的二分寫的我心慌,整個都是反過來的。。
// bzoj3110#include#include#include#include#include#include#define ll long long
#define mod 100000000
#define inf 2147483640
#define pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
const int maxn=50010;
struct data a[maxn],tr[maxn],tl[maxn];
ll c1[maxn],c2[maxn];
int ans[maxn],n,m;
int lowbit(int x)
ll query(int x)
void add(int x,int val)
void solve(int l,int r,int l,int r)
int mid=(l+r+1)>>1,ll=0,rr=0,fl=0,fr=0;
for (int i=l;i<=r;i++)
else
} for (int i=l;i<=r;i++) if (a[i].t==1 && a[i].k>=mid) add(a[i].l,-1),add(a[i].r+1,1);
for (int i=1;i<=ll;i++) a[l+i-1]=tl[i];
for (int i=1;i<=rr;i++) a[l+ll+i-1]=tr[i];
if (fl) solve(l,l+ll-1,l,mid-1);
if (fr) solve(l+ll,r,mid,r);
}int main()
solve(1,m,1,n);
for (int i=1;i<=tot;i++) printf("%d\n",ans[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...
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的值 把區間加操作也按照權值兩邊下放,每次詢問完答案...