数据结构
知识点目录
1 栈
2 队列
3 优先队列(堆)
4 map
5 vector
6 set
7 链表
8 并查集
9 树状数组
10
题目目录
1 树状数组 LGP3374
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
//#define lowbit(i) i&(-i)
using namespace std;
int n,m;
int p[500005],a[500005];
int lowbit(int i){
return i&(-i);
}
void changex(int num,int h){
for(int i=num;i<=n;i+=lowbit(i)){
a[i]+=h;
}
return ;
}
int findx(int x){
int sum=0;
for(int i=x;i;i-=lowbit(i)){
sum+=a[i];
}
return sum;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}
for(int i=1;i<=n;i++){
changex(i,p[i]);
}
while(m--){
int b=0,x=0,y=0;
scanf("%d%d%d",&b,&x,&y);
if(b==1){
changex(x,y);
}
if(b==2){
printf("%d\n",findx(y)-findx(x-1));
}
}
return 0;
}
2 树状数组 2 LGP3368
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m;
int z[500005],a[500005],p[500005];
int lowbit(int i){
return i&(-i);
}
void changex(int num,int h){
for(int i=num;i<=n;i+=lowbit(i)){
a[i]+=h;
}
return ;
}
void addd(int x,int y,int z){
changex(x,z);
changex(y+1,-z);
return ;
}
int findx(int x){
int sum=0;
for(int i=x;i;i-=lowbit(i)){
sum+=a[i];
}
return sum;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}
z[1]=p[1];
for(int i=2;i<=n;i++){
z[i]=p[i]-p[i-1];
}
for(int i=1;i<=n;i++){
changex(i,z[i]);
}
while(m--){
int b=0,x=0,y=0,z=0;
scanf("%d",&b);
if(b==1){
scanf("%d%d%d",&x,&y,&z);
addd(x,y,z);
}
if(b==2){
scanf("%d",&x);
printf("%d\n",findx(x));
}
}
return 0;
}
3 最大数[BZOJ1012][JSOI2008]LGP1198
题解
可以发现一个数如果右面有比他还大的数,那他永远都不可能成为 答案了
那么我们就只需要维护一个单调递减的栈
每次二分查询即可
显然不能使用STL的栈,因为这道题需要我们访问栈内元素
4 树 [JLOI2012] LGP3252
题解
DFS 一遍整颗树
当便利到一个点时将这个点加入队列,同时队头向 后调整,使队列中元素之和 \(<les\) 记录 \(ans\)
当一个点出栈时将队尾删除,同时队头向前调整,使队列中元素之和刚好 \(\leq s\)
显然需要使用双端队列