好吧这是寒假时候的事了。然而三个数据结构(线段树、树状数组、st表)里面我就听懂了线段树。真是太惨了。而我之前也没有把线段树的操作搞清楚。真是惨死了。
好吧,根据网上各位大佬的题目汇总里面最基础的几道题刷过以后有几个感想。线段树果然还是又臭又长啊。容易编错。
hudu1166 敌兵布阵
#include<cstdio>
#include<cstring>
#define N 100010
using namespace std;
int T, n, t, a[N];
struct Node {
int sum, flag;
Node *ls, *rs;
void pushdown(int l, int r) {
if(flag) {
int mid = (l + r) >> 1;
ls->flag += flag;
ls->sum += (mid - l + 1) * flag;
rs->flag += flag;
rs->sum += (r - mid) * flag;
flag = 0;
}
}
void update() {
sum = ls->sum + rs->sum;
}
}pool[N * 10], *tail = pool, *root;
Node *build(int l, int r) {
Node *bt = ++tail;
if(l == r) {
bt->sum = a[l];
bt->flag = 0;
}
else {
int mid = (l + r) >> 1;
bt->ls = build(l, mid);
bt->rs = build(mid + 1, r);
bt->sum = bt->ls->sum + bt->rs->sum;
bt->flag = 0;
}
return bt;
}
void modify(int pos, int delta, int l, int r, Node *bt) {
if(l == pos && r == pos) {
bt->sum += delta;
bt->flag += delta;
return ;
}
int mid = (l + r) >> 1;
bt->pushdown(l, r);
if(pos <= mid)
modify(pos, delta, l, mid, bt->ls);
if(pos > mid)
modify(pos, delta, mid + 1, r, bt->rs);
bt->update();
}
int query(int L, int R, int l, int r, Node *bt) {
if(l >= L && r <= R) {
return bt->sum;
}
int mid = (l + r) >> 1;
int rt = 0;
bt->pushdown(l, r);
if(L <= mid)
rt += query(L, R, l, mid, bt->ls);
if(R > mid)
rt += query(L, R, mid + 1, r, bt->rs);
return rt;
}
int main() {
scanf("%d", &T);
for(int i = 1; i <= T; i++) {
printf("Case %d:\n", i);
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
root = build(1, n);
char s[10];
scanf("%s", s);
while(s[0] != 'E') {
if(s[0] == 'A') {
int pos, delta;
scanf("%d%d", &pos, &delta);
modify(pos, delta, 1, n, root);
}
if(s[0] == 'S') {
int pos, delta;
scanf("%d%d", &pos, &delta);
modify(pos, -delta, 1, n, root);
}
if(s[0] == 'Q') {
int L, R;
scanf("%d%d", &L, &R);
printf("%d\n", query(L, R, 1, n, root));
}
scanf("%s", s);
}
}
return 0;
}
其实没刷几道题,主要还是为了练下手,毕竟这个线段树很有名堂,很多东西都可以套。数据结构别的可以放放,这个必须要掌握啊!