有n個位置,m個操作。操作有兩種,每次操作如果是:
2 a b c
:表示詢問從第a個位置到第b個位置,第c大的數是多少。
輸入格式:
第一行n,m接下來m行,每行形如1 a b c或2 a b c
輸出格式:
輸出每個詢問的結果
solution
整體二分。
假設我們現在要解決[ql,qr] 並且他們的答案(加數操作就是值)在[l,r]
二分乙個mid,我們維護乙個區間。
我們把》=mid的操作對應區間都加1
對於詢問,如果對應區間的值》=c,說明mid-r有最少c個了,那麼它的答案就在[mid,r]裡。
否則把值減去區間對應值,丟進[l,mid-1]裡。
樹狀陣列有個高階的區間加區間查寫法,維護差分和差分*i
#include#includeview code#include
#include
#include
#include
#define maxn 500005
using
namespace
std;
intn,m,max,t1[maxn],t2[maxn];
struct
nodeq[maxn],s[maxn];
void add(int x,int
v)int ask(int
x)
return
sum;
}void solve(int l,int r,int ql,int
qr)
int mid=l+r+1>>1
;
int p=ql;
for(int i=ql;i<=qr;i++)
else p++;
}else
}int n1=ql,n2=p;
for(int i=ql;i<=qr;i++)
else s[n1++]=q[i];
}else
else s[n2++]=q[i];}}
for(int i=ql;i<=qr;i++)q[i]=s[i];
solve(l,mid-1,ql,p-1
);solve(mid,r,p,qr);
}bool id(node a,node b)
intmain()
solve(
1,max,1
,m);
sort(q+1,q+m+1
,id);
for(int i=1;i<=m;i++)
}return0;
}
posted @
2019-02-21 09:24
liankewei123456 閱讀(
...)
編輯收藏
ZJOI2013 K大數查詢
有n個位置,m個操作。1 a b c形式,表示在第a個位置到第b個位置,每個位置加入乙個數c 2 a b c形式,表示詢問從第a個位置到第b個位置,第c大的數是多少。區間的第k大值有一種二分的做法。二分答案mid,計算出區間內 mid的值有多少個。若數量小於c,則ans mid,否則ans mid。...
ZJOI2013 K大數查詢
點此看題 0x01 樹套樹 這道題的思路特別巧妙,樹套樹不一定要用區間線段樹套權值線段樹,還可以反過來套。我們維護乙個動態開點的權值線段樹,每個點代表權值 l,r l,r l,r 在整個區間的出現情況,套上乙個動態開點的區間線段樹,操作1 11對權值線段樹單點修改,然後對每個點的 a,b a,b a...
ZJOI2013 K大數查詢
顯然可以線段樹套線段樹。但是必須卡常。所以我採用了整體二分。注意是區間第k大,而不是第k小。然後區間轉化一下即可。有乙個剪枝的地方,就是如果這個區間已經沒有查詢的操作了,那就不用遞迴了。ac pragma gcc optimize ofast funroll all loops include de...