SPOJ D query 可持久化線段樹

2021-09-19 16:46:21 字數 1318 閱讀 7305

題目描述:多次詢問乙個區間內不同數的數量。

解題思路:乙個區間內存在相同的數,所以我們的線段樹就不能維護數,應該去維護下標?為什麼去維護下標呢,就算乙個數相同,但是它們的下標肯定是不同的,我們的線段樹維護下標存在的情況。

如果區間內存在重複的數,意味著不同下標對應相同的數,如果我們記錄多個下標答案就會重複,我們要怎麼去解決這個問題呢?

我們把下標右移(相同的數,我們記錄的下標只記錄最右邊的那乙個)。因為如果這個數出現過,為了維護這個狀態的線段樹,就應該記錄下當前的這個下標,取消以前的標記。

我們查詢答案時,只需要查詢在 r 時刻狀態的線段中在 [ l , r ] 區間內下標存在的個數就是答案。

細節請看**:

///#include///#include///#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#define mt(a, b) memset(a,b,sizeof(a));

#define lowbit(x) (x&(-x));

using namespace std;

typedef long long ll;

typedef unsigned long long ull;

const double pai = acos(-1.0);

const double e = 2.718281828459;

const ll mod = 20071027;

const ll inf = 0x3f3f3f3f3f3f;

const int maxn = 3e4 + 5;

struct node p[maxn * 40];

int root[maxn], times;

int pos[1000005];

void insert(int &now, int old, int l, int r, int sub, int x)

int query(int now, int l, int r, int a, int b)

void init()

int main() else

insert(root[i], root[i - 1], 1, n, i, 1);

pos[x] = i;

}scanf("%d", &op);

while (op--)

}

可持久化Treap

本來是想寫一點題的,但是hfu最近讓我改鍵盤指法,原來都是亂打 手速蠻快就是錯的多 剛開始練手法真的煩躁,像我這種從來不用小指頭的 就寫個學習筆記吧.非教程向,只是懂了後寫點隨筆,練成指法說不定能來填坑.可持久化treap首先是基於非旋轉式treap的,如果要旋轉的話那麼就會破壞父子關係導致無法可持...

可持久化Treap

可持久化treap本質上市乙個二叉平衡樹,若不對其規則進行修改,中序遍歷後得出的序列是遞增的。void maintain o 計算結點o的size int lowcount key 比key所在位置小1 int uppercount key key所在的位置,如果有多個相同的key,選位置最大的 i...

可持久化專題

一切之始主席樹 可持久化並查集 首先可持久化並查集我們是用主席樹來維護的,葉子節點維護每個位置的fa 維護2個量 每個點的父親和每棵樹的根節點的高度。那麼不使用路徑壓縮的話這個版本的主席樹和上個版本的主席樹 有且只有乙個點會被改動。那麼就可以進行可持久化了。既然取消了路徑壓縮,為了保證複雜度,我們需...