hdu4358 樹狀陣列 非常經典

2021-06-10 08:50:43 字數 1262 閱讀 3982

碰到過類似這題幾次都做不出,只因為始終不理解

1.深搜後樹上的某點的子樹變成陣列的乙個區間,網上有人估計寫挫了,說會爆棧,我不會,

最好不用vector,會tle,這題資料挺強的,後來改了鄰接表過了,事實證明,鄰接表還是時間空間都有很好效果的做法

2.講詢問按右端點排序,每次插入更新,如果有這個是某個詢問的右端點,就詢問

3.在插入到某點i是,第k(1<=k<=i)表示k到i的答案,要明白:

每插入新的一點,改變的只有插入的這個數,設這個數p出現的位置是p0,p1,p2...pj-k-1,pj-k,pj-k+1....pj-1,

如果詢問的左端點在(pj-k-1,pj-k],右端點在i,p就湊夠k次

現在在pj=i插入新的數p,就變成如果詢問的左端點在(pj-k,pj-k+1],p湊夠k次,

而左端點在(pj-k-1,pj-k]的p出現的次數變成k+1,不是答案,

所以樹狀陣列的操作是(pj-k-1,pj-k] 區間-1,(pj-k,pj-k+1]區間+1,然後詢問左端點的值就好了(因為樹狀陣列上第k位表示k到i的答案)

可見要用到的操作:區間更新,單點詢問,用第二類樹狀陣列

~~1.離散化的時候搞錯,一直re不止

~~2vector用的過多導致tle

~~3.最後還pe了。。。

果然歷經艱辛啊

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

#define n 105000

int edge[n*2],head[n*2],adj[n*2],e;

int dfn[n],low[n],val[n],n,k,w[n],cnt,q;

vectorvec[n];

int vis[n];

struct query

que[n];

bool cmp(query left,query right)

return ret;

}int main ()

update(vec[val[i]][size-k]+1,1);

update(vec[val[i]][size-k+1]+1,-1);

}while(que[q_index].r==i&&q_index<=q)

}printf("case #%d:\n",k);

for(int i=1;i<=q;++i)

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

if(k

hdu 4358 莫隊演算法 dfs序列

解題思路 用dfs求出整棵樹的dfs序列,這樣以u為根節點的子樹就轉化到相對應的區間上了。由於是區間不修改查詢問題,這個時候就可以用莫隊演算法了。pragma comment linker,stack 16777216 include include include include includeu...

hdu 4358 深搜時間戳 線段樹更新

其實這道題真的告訴了我乙個道理,那就是仔細看題,題目中明確說出了1就是所有子樹的根結點。我們可以想一想,現在每個結點代表著一段區間的詢問,所以我們必須利用深搜的時間戳來找出所有結點所代表的區間。前向星見圖自然不可少。更新區間的話,我們必須用離線處理,i,j 這個區間代表著第i個數在這個區內出現k次的...

HDU1541 經典樹狀陣列

hdu1541 題意 如圖,等級為0的點有1,等級為1得點有4,2 等級為2的點有3,等級為3的點有5 即即左下角的點的個數 現給你一些點 x,y 輸入順序按y公升序,y相等時按x公升序排列 請分別輸出等級0 n 1的點的個數 分析 暴力超時tel,用g 提交也超時 include include ...