K大數查詢 BZOJ 3110

2022-08-20 03:48:07 字數 2825 閱讀 5295

k大數查詢

【問題描述】

有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

【輸出格式】

輸出每個詢問的結果

【樣例輸入】

2 51 1 2 1

1 1 2 2

2 1 1 2

2 1 1 1

2 1 2 3

【樣例輸出】12

1【樣例說明】

第乙個操作 後位置 1 的數只有 1 , 位置 2 的數也只有 1 。

第二個操作 後位置 1的數有 1 、 2 ,位置 2 的數也有 1 、 2 。

第三次詢問 位置 1 到位置 1 第 2 大的數 是1 。

第四次詢問 位置 1 到位置 1 第 1 大的數是 2 。

第五次詢問 位置 1 到位置 2 第 3大的數是 1 。‍

【資料範圍】

n,m<=50000,n,m<=50000,a<=b<=n

1操作中abs(c)<=n,2操作中c<=maxlongint

題解:我們將詢問離線,做整體二分

題目中有負數,那麼我們轉化一下,將每個數變為n-i+1,輸出答案時再變為n-ans+1

對於乙個操作1,如果這個操作加入的c是不超過mid的

用線段樹在區間內加1,表示此區間小於等於mid的數多了乙個,那麼將它放置到左區間

否則將其放置到右區間,表示這個操作的貢獻在右區間

對於乙個操作2,查詢在區間內小於等於mid的數的個數tot

如果tot超過k,將其放置到左區間,表示答案在左區間

否則將k減去tot,放置到右區間,表示需要在右區間找k-tot大的數

1 #include2 #include3 #include4 #include5 #include6 #include7

using

namespace

std;

8struct s a[1000001], c[1000001];9

bool lr[1000001

];10

long

long n, m, tot, maxx = -2147483647;11

long

long sum[1000001], ans[1000001], node[1000001

];12

void down(long

long k, int l, int

r)1323}

24void inc(int k, int l, int r, int x, int y, int

z)25

32down(k, l, r);

33int mi = (l + r) >> 1;34

if(mi >= x) inc(k * 2

, l, mi, x, y, z);

35if(mi < y) inc(k * 2 + 1, mi + 1

, r, x, y, z);

36 sum[k] = sum[k * 2] + sum[k * 2 + 1

];37}38

long

long sum(long

long k, long

long l, long

long r, long

long x, long

long

y)39

47void two(long

long x, long

long y, long

long l, long

long

r)48

58long

long temp, s =x;

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

6069

else

7074}75

else

7683

else lr[i] = false;84

}85}86

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

87if(!a[i].flag && a[i].z <=mi)

88 inc(1, 1, 2 * n + 1, a[i].x, a[i].y, -1

);89

long

long o =x;

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

91if(lr[i]) c[o++] =a[i];

92else c[s++] =a[i];

93for(int i = x; i <= y; ++i) a[i] =c[i];

94 two(x, o - 1, l, mi), two(o, y, mi + 1

, r);

95}

96int

main()

97108

else a[i].id = ++tot;

109}

110 two(1, m, 1

, maxx);

111for(int i = 1; i <= tot; ++i) printf("

%lld\n

", n - ans[i] + 1

);112 }

K大數查詢(bzoj 3110)

有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 輸出每個詢問的結果 2 51 1 2...

BZOJ 3110, K大數查詢

傳送門 要求維護乙個數列,支援在某部分的每個位置填上乙個數以及查詢某部分第k大的數字。終於學習了一下樹套樹的姿勢 其實和自己想的也差不多 但是不學還是打不出 來 外層是權值線段樹,內層是區間線段樹。要注意的細節比較多。二分查詢過程中結果可能超過maxlongint,需要用unsigned int型別...

bzoj 3110 K大數查詢 樹套樹

題目傳送門 time limit 20 sec memory limit 512 mb submit 5039 solved 1751 submit status discuss 有n個位置,m個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入乙個數c ...