hdu 6133 樹狀陣列 分類討論

2022-08-19 20:12:13 字數 1478 閱讀 6455

題意:。。比較複雜,就是乙個樹有點權,乙個點的答案是子樹的所有點權的字首和的和(貪心思想轉換後的題意),問所有答案。

首先這是個假題解。。只是提供乙個思路。。。資料不強ac了。。。

思路:標解是個啟發式合併。。這裡嘗試另一種做法(因為不會),平均時間複雜度是nlogn^2。(資料弱。。)考慮合併操作複雜,我們可以分為合併暴力,單個兒子直接得答案兩種操作解決問題。(看起來很玄學。。),事實上是這樣的,單個兒子的時間複雜度不用解釋,肯定是正確的,我們只要維護子樹離散化後的個數以及乙個sum。對於暴力這部分。。其實也是一拍腦子想出來的。。首先有乙個二叉結點我們就要暴力他的子樹一次,當他是乙個滿二叉樹的時候,整個排序的過程就類似乙個歸併樹(事實上多乙個sort的log),那麼其實這個暴力就類似快排了,隨機資料下時間複雜度是科學的。。

**:#includeusing namespace std;

#define mem(a,b) memset(a,b,sizeof(a))

#define bug puts("bug");

#define pb push_back

#define mp make_pair

#define x first

#define y second

typedef unsigned long long ll;

typedef pairpii;

const int maxn=1e5+100;

const int mod=1e9+7;

using namespace std;

ll sum;

int id[maxn],l[maxn],r[maxn],x,y,n,t,tim,cnt[maxn];

ll b[maxn],a[maxn],hs[maxn],bit[maxn],ans[maxn],sbit[maxn];

vectorv[maxn];

void add(int x,int y)

int dfs(int x,int f)

modify(id[x],1,bit);

modify(id[x],a[x],sbit);

}int main(){

scanf("%d",&t);

while(t--){

scanf("%d",&n);

tim=1;

mem(sbit,0),mem(bit,0);mem(ans,0);mem(cnt,0);

for(int i=0;i<=n+2;i++) v[i].clear();

for(int i=1;i<=n;i++) scanf("%lld",&a[i]);

for(int i=1;i<=n;i++) hs[i]=a[i];

sort(hs+1,hs+n+1);

int n=unique(hs+1,hs+n+1)-hs;

for(int i=1;i<=n;i++) id[i]=lower_bound(hs+1,hs+n,a[i])-hs+1;

for(int i=0;i

hdu 3887 樹狀陣列

給你一棵樹,每個節點都有個編號。讓你求乙個節點他的子樹中編號比他小的節點有幾個。編號唯一,從1 n,已給出根節點 解 樹狀陣列統計。轉化為線性序列。可以想到的是,若要統計乙個節點,那麼比它小的孩子必須先插完,然後統計就行了。對於乙個節點i來說,只要把所有x那麼對於所有節點來說也是這樣的,從一開始插,...

hdu 3333 樹狀陣列

此題與3743相仿,但本題資料較大,需要用到離散化。如何去掉重複元素呢?採用離線演算法 首先將詢問按右端點從小到大排序,離線處理時,記錄每個元素所在位置,遇到重複元素時,從它之前出現的位置減去這個元素,這樣就是的每個元素總是出現在最後。include include include include ...

樹狀陣列 HDU1166

繼續上次那題,我們現在採用樹狀陣列來解。樹狀陣列主要用來進行區間求和統計和定點更新操作,樹狀陣列的儲存是如下方式的 假設陣列a為a 1 a 2 a 3 a n 現在我們另陣列c 1 a 1 c 2 a 1 a 2 c 3 a 3 c 4 a 1 a 2 a 3 a 4 這是啥結構呢?其實c i a ...