hdu4638 Group(樹狀陣列)

2021-07-04 21:21:29 字數 1777 閱讀 1247

題目大意:

給乙個1-n的排列,然後詢問[x,y]區間中有多少個連續的段。

如給乙個3 1 2 5 4, 查詢是2 4,那麼就是問1 2 5中有多少個連續的串,一共有兩個串,1、2為乙個串,5為乙個串

若查詢是2 5,則問的是1 2 5 4中有多少個連續的串,一共有兩個串, 1、2為乙個串, 4、5 為乙個串。

反思:這一題我想了蠻久的,因為我一直想要去維護每乙個串的首個數字,但想了很久都沒有想到維護的方法。

後面看了題解後才發現,不僅僅可以通過數串數得到答案,還可以通過一段區間中有多少個相鄰的數字對,來得到答案。

若查詢區間中有k個相鄰數字對,區間長度是m,那麼這次的答案就是m - k。

這個其實蠻好理解的,大家舉幾個例子仔細想一下就明白了。

像1 2 5 4,其中1和2、4和5是相鄰的數字對,所以答案就是 4 - 2 = 2

現在問題就變成了求一段區間當中有多少個相鄰的數字對。

我的解決方法是進行離線查詢,對m個詢問按照x的大小,從大到小排序,然後根據查詢,依次更新區間[n, n], [n-1, n]. [n-2, n] , [n-3, n], [n-4, n] ........ [2, n], [1, n]的數字對的情況:

具體更新方法:從[i+1, n]更新到[i, n],若pos[a[i]+1] > i , 則updata(pos[a[i]+1], 1)。若pos[a[i]-1] > i ,則updata(pos[a[i-1]]. 1)。否則不進行操作。

具體更新**

void updata(int val, int posx)

j = n + 1;

for (i=m; i>=1; i--)

ans[q[i].id] = (q[i].y - q[i].x + 1) - query(q[i].x, q[i].y);

}

在這個更新基礎上,查詢就只要直接用樹狀陣列查詢區間合就好了。

最後附上全部**:

#include #include #include #include using namespace std;

const int maxn = 1e5 + 100;

class query

;bool operator < (const query &a, const query &b)

query q[maxn];

int a[maxn], pos[maxn], ans[maxn], h[maxn];

int n, m;

int lowbit(int x)

void updata_tree(int x, int val)

return;

}int query_tree(int x)

return ans;

}void updata(int val, int posx)

int query(int x, int y)

int main()

for (i=1; i<=m; i++)

sort(q+1, q+m+1);

j = n + 1;

for (i=m; i>=1; i--)

ans[q[i].id] = (q[i].y - q[i].x + 1) - query(q[i].x, q[i].y);

} for (i=1; i<=m; i++)

printf("%d\n", ans[i]);

} return 0;

}

hdu 4638 Group 樹狀陣列

題意 找到區間裡有多少組連續數字串 分析 思路 顯然,我們要使得value最大,就要盡量將連續的id分在一組,所以問題轉化為求乙個區間中連續id區間的個數。我們從左往右掃瞄,依次考慮右端點為i的詢問,設dp l 為區間 l,i 的連續區間個數,po i 為i出現的位置,若還未出現,則為0,設我們當前...

HDU 4638 Group 樹狀陣列

詢問一段區間裡的數能組成多少段連續的數。先考慮從左往右乙個數乙個數新增,考慮當前新增了i 1個數的答案是x,那麼可以看出新增完i個數後的答案是根據a i 1和a i 1是否已經新增而定的 如果a i 1或者a i 1已經新增乙個,則段數不變,如果都沒新增則段數加1,如果都新增了則段數減1。設v i ...

Hdu 4638 Group 離線 樹狀陣列

題目大意 給你1 n的任意全排列,詢問q次,每次詢問區間 l r 內的組數,組數的定義為 在乙個連續區間中,可以把區間中的數任意分成幾組,每組的所有數必須連續,比如 7 5 8的組數為2,即7,8和5。解題思路 先假設每個數都是一組,然後查詢和他相鄰的兩個數是否在此之前出現過,如果出現則 出現的位置...