有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
輸出每個詢問的結果
題目大意:略。
思路:分治答案。答案範圍[-n, n],從前往後掃瞄,若是插入操作且c>mid,則把線段樹中區間[a, b]加一,並置為為類別1;否則置為類別0。若是詢問操作,若目前線段樹中區間[a, b]的和小於等於c,則置為類別1;否則置為類別0,並把c減去區間[a, b]的和。然後分治處理,其中類別0中,答案範圍為[-n, mid];類別1中,答案範圍為[mid + 1, n]。按類別排序後,兩個區間之間互不影響。時間複雜度為o(nlognlogn)。
**(4940ms):
1 #include 2 #include 3 #include 4 #include 5view codeusing
namespace
std;
6 typedef long
long
ll;7
8const
int maxn = 50010;9
const
int maxt = maxn << 2;10
11int
sum[maxt];
12int
add[maxt];
13bool
clr[maxt];
1415
#define ll (x << 1)
16#define rr (ll | 1)
17#define mid ((l + r) >> 1)
18void
inittree()
2223
void pushdown(int x, int l, int
r) 29
if(add[x]) 36}
3738
void maintain(int
x) 41
42void modify(int x, int l, int r, int a, int
b) else52}
5354
int query(int x, int l, int r, int a, int
b) else64}
65#undef mid
6667
struct
node
73bool
operator
< (const node &rhs) const
77} p[maxn];
78int
ans[maxn];
79int
n, m;
8081
void work(int a, int b, int l, int
r) 88
inittree();
89int mid = a + ((b - a) >> 1), t = l - 1;90
for(int i = l; i <= r; ++i) else
99 t += !p[i].v;
100}
101 sort(p + l, p + r + 1
);102
work(a, mid, l, t);
103 work(mid + 1, b, t + 1
, r);
104}
105106
intmain()
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大數查詢
有n個位置,m個操作。操作有兩種,每次操作如果是 2 a b c 表示詢問從第a個位置到第b個位置,第c大的數是多少。輸入格式 第一行n,m接下來m行,每行形如1 a b c或2 a b c 輸出格式 輸出每個詢問的結果 solution 整體二分。假設我們現在要解決 ql,qr 並且他們的答案 加...
ZJOI2013 K大數查詢
點此看題 0x01 樹套樹 這道題的思路特別巧妙,樹套樹不一定要用區間線段樹套權值線段樹,還可以反過來套。我們維護乙個動態開點的權值線段樹,每個點代表權值 l,r l,r l,r 在整個區間的出現情況,套上乙個動態開點的區間線段樹,操作1 11對權值線段樹單點修改,然後對每個點的 a,b a,b a...