題目描述:多次詢問乙個區間內不同數的數量。
解題思路:乙個區間內存在相同的數,所以我們的線段樹就不能維護數,應該去維護下標?為什麼去維護下標呢,就算乙個數相同,但是它們的下標肯定是不同的,我們的線段樹維護下標存在的情況。
如果區間內存在重複的數,意味著不同下標對應相同的數,如果我們記錄多個下標答案就會重複,我們要怎麼去解決這個問題呢?
我們把下標右移(相同的數,我們記錄的下標只記錄最右邊的那乙個)。因為如果這個數出現過,為了維護這個狀態的線段樹,就應該記錄下當前的這個下標,取消以前的標記。
我們查詢答案時,只需要查詢在 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個量 每個點的父親和每棵樹的根節點的高度。那麼不使用路徑壓縮的話這個版本的主席樹和上個版本的主席樹 有且只有乙個點會被改動。那麼就可以進行可持久化了。既然取消了路徑壓縮,為了保證複雜度,我們需...