其實這道題真的告訴了我乙個道理,那就是仔細看題,題目中明確說出了1就是所有子樹的根結點。
我們可以想一想,現在每個結點代表著一段區間的詢問,所以我們必須利用深搜的時間戳來找出所有結點所代表的區間。
前向星見圖自然不可少。
更新區間的話,我們必須用離線處理,[i,j]這個區間代表著第i個數在這個區內出現k次的數的個數。
view code
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8
using
std::sort;
9using
std::vector;
10using
std::map;
11const
int n = 100111
;12 mapq;
13 vectorp[n];
14struct
edge
15edge[n<<1
];18
inthead[n],weight[n],visit[n],ti;
19struct
query
2026
}que[n];
27struct
node
28no[n];
31int cover[n<<2
],num[n],ans[n];
32void dfs(int
u)3344}
45 no[u].r=ti;46}
47void pushdown(int
t)48
56return;57
}58void update(int t,int l,int r,int l,int r,int
val)
5965
pushdown(t);
66int m=(r+l)>>1;67
if(l<=m)update(t<<1
,l,m,l,r,val);
68if(r>m)update(t<<1|1,m+1
,r,l,r,val);69}
70int query(int t,int l,int r,int
i)71
78int
main()
7995
int tope=0;96
for(int i=0;i)
97p[i].clear();
98for(int i=1;i)
99108 visit[1]=ti=1
;109 dfs(1
);110 scanf("
%d",&q);
111for(int i=1;i<=q;i++)
112118 sort(que+1,que+q+1
);119 memset(cover,0,sizeof
(cover));
120for(int i=1,j=1;i<=n;i++)
121129
else
130if(count==k)
131 update(1,1,n,1,p[num[i]][count-k],1
);132
while(i>=que[j].r)
133138
if(j>q)break
;139
}140
if(t!=0)printf("\n"
);141 printf("
case #%d:\n
",++t);
142for(int i=1;i<=q;i++)
143 printf("
%d\n
",ans[i]);
144}
145return0;
146 }
hdu4358 樹狀陣列 非常經典
碰到過類似這題幾次都做不出,只因為始終不理解 1.深搜後樹上的某點的子樹變成陣列的乙個區間,網上有人估計寫挫了,說會爆棧,我不會,最好不用vector,會tle,這題資料挺強的,後來改了鄰接表過了,事實證明,鄰接表還是時間空間都有很好效果的做法 2.講詢問按右端點排序,每次插入更新,如果有這個是某個...
hdu 4358 莫隊演算法 dfs序列
解題思路 用dfs求出整棵樹的dfs序列,這樣以u為根節點的子樹就轉化到相對應的區間上了。由於是區間不修改查詢問題,這個時候就可以用莫隊演算法了。pragma comment linker,stack 16777216 include include include include includeu...
hdu 1010 深搜 回溯
也不想解釋了,只是做來找回做題的感覺。遲d出個這方面的小總結,越來越發現對所學知識作總結的重要性了 1010tempter of the bone include includeint n,m,time int xs,ys,xd,yd int direc 4 2 char str 11 11 boo...