线段树题集

/**
*  单点更新,区间查询
**/

///hrb1752(单点替换,查询区间最大值及下标)
///代码:
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 111111;
int maxn[MAXN<<2];
int posn[MAXN<<2];
///把当前节点的信息更新到父节点
void pushUp(int rt) {
   if (maxn[rt<<1] > maxn[rt<<1|1]) {///确保最大值相等时,rt节点保存的是rt<<1|1节点的信息
      maxn[rt] = maxn[rt<<1];
      posn[rt] = posn[rt<<1];
   }else {
      maxn[rt] = maxn[rt<<1|1];
      posn[rt] = posn[rt<<1|1];
   }
}
///建树
void build(int l, int r, int rt) {
   if (l == r) {
      scanf("%d", &maxn[rt]);
      posn[rt] = l;
   }else {
      int m = (l + r) >> 1;
      build(LSON);
      build(RSON);
      pushUp(rt);
   }
}
///单点替换
void update(int p, int val, int l, int r, int rt) {
   if (l == r) {
      maxn[rt] = val;
   }else {
      int m = (l + r) >> 1;
      if (p <= m) {
         update(p, val, LSON);
      }else {
         update(p, val, RSON);
      }
      pushUp(rt);
   }
}
///查询区间最大值及最大值的标号
int query(int L, int R, int l, int r, int rt, int *pos) {///pos存储page编号
   if (L <= l && r <= R) {
      *pos = posn[rt];
      return maxn[rt];
   }else {
      int m = (l + r) >> 1;
      int ret1 = INT_MIN;
      int ret2 = INT_MIN;
      int pa, pb;
      int *pos1 = &pa;
      int *pos2 = &pb;
      if (L <= m) {
         ret1 = query(L, R, LSON, pos1);
      }
      if (R > m) {
         ret2 = query(L, R, RSON, pos2);
      }
      if (ret1 > ret2) {
         *pos = pa;  ///最大值标号
      }else {
         *pos = pb;  ///最大值标号
         ret1 = ret2;
      }
      return ret1;   ///最大值
   }
}


///hdu1166(单点增减,查询区间和)
///代码:
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 55555;
int sum[MAXN<<2];
///把当前节点的信息更新到父节点
void pushUp(int rt) {
   sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
///建树
void build(int l, int r, int rt) {
   if (l == r) {
      scanf("%d", &sum[rt]);
   }else {
      int m = (l + r) >> 1;
      build(LSON);
      build(RSON);
      pushUp(rt);
   }
}
///更新单点值(减去或加上一个值)
void update(int p, int add, int l, int r, int rt) {
   if (l == r) {
      sum[rt] += add;
   }else {
      int m = (l + r) >> 1;
      if (p <= m) {
         update(p, add, LSON);
      }else {
         update(p, add, RSON);
      }
      pushUp(rt);
   }
}
///查询区间和
int query(int L, int R, int l, int r, int rt) {
   if (L <= l && r <= R) {
      return sum[rt];
   }else {
      int m = (l + r) >> 1;
      int ret = 0;
      if (L <= m) {
         ret += query(L, R, LSON);
      }
      if (R > m) {
         ret += query(L, R, RSON);
      }
      return ret;
   }
}


/**
*  成段更新,区间查询
**/

///hdu4027(成段开方,区间查询)
/**
*  题意:给出n(1<=n<=100000)个整数,m(1<=m<=100000)次操作,
*  操作1:对区间[a,b]内的每个数开方,结果向下取整,
*  操作2:查询区间[a,b]的总和。
*  分析:一个整数(>=1)经过多次开方后结果变为1,
*  如果一个区间的所有整数都为1,则该区间不再需要更新。
**/

///代码1:
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 111111;
__int64 sum[MAXN<<2];
///把当前节点的信息更新到父节点
void pushUp(int rt) {
   sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
///建树
void build(int l, int r, int rt) {
   if (l == r) {
      scanf("%I64d", &sum[rt]);
   }else {
      int m = (l + r) >> 1;
      build(LSON);
      build(RSON);
      pushUp(rt);
   }
}
///成段更新(每个值开方)
void update(int L, int R, int l, int r, int rt) {
   if (l == r) {   ///更新叶子节点
      sum[rt] = (__int64)sqrt((double)sum[rt]);
   }else {
      int m = (l + r) >> 1;
      ///(注意:此题数据中没有0,都为正整数,若有,则该判断条件不对,该解法不对)
      if (L <= m && ((__int64)(m-l+1) != sum[rt<<1])) {///判断是否要更新左子树
         update(L, R, LSON);
      }
      ///(注意:此题数据中没有0,都为正整数,若有,则该判断条件不对,该解法不对)
      if (R > m && ((__int64)(r-m) != sum[rt<<1|1])) {///判断是否要更新右子树
         update(L, R, RSON);
      }
      pushUp(rt);
   }
}
///查询区间和
__int64 query(int L, int R, int l, int r, int rt) {
   if (L <= l && r <= R) {
      return sum[rt];
   }else {
      int m = (l + r) >> 1;
      __int64 ret = 0;
      if (L <= m) {
         ret += query(L, R, LSON);
      }
      if (R > m) {
         ret += query(L, R, RSON);
      }
      return ret;
   }
}

///代码2:数据中可以有0
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 111111;
__int64 sum[MAXN<<2];
///1为需要更新,0为不需要更新
__int64 flag[MAXN<<2];///是否要更新的标志(只要区间中有数据大于1,则该区间就要更新)
///把当前节点的信息更新到父节点
void pushUp(int rt) {
   sum[rt] = sum[rt<<1] + sum[rt<<1|1];
   flag[rt] = flag[rt<<1] || flag[rt<<1|1];
}
///建树
void build(int l, int r, int rt) {
   if (l == r) {
      scanf("%I64d", &sum[rt]);
      flag[rt] = (sum[rt] <= 1 ? 0 : 1);
   }else {
      int m = (l + r) >> 1;
      build(LSON);
      build(RSON);
      pushUp(rt);
   }
}
///成段更新(每个值开方)
void update(int L, int R, int l, int r, int rt) {
   if (flag[rt] != 0) {///判断是否需要更新区间
      if (l == r) {   ///更新叶子节点
         sum[rt] = (__int64)sqrt((double)sum[rt]);
         flag[rt] = (sum[rt] <= 1 ? 0 : 1);
      }else {
         int m = (l + r) >> 1;
         if (L <= m) {///更新左子树
            update(L, R, LSON);
         }
         if (R > m) {///更新右子树
            update(L, R, RSON);
         }
         pushUp(rt);
      }
   }
}
///查询区间和
__int64 query(int L, int R, int l, int r, int rt) {
   if (L <= l && r <= R) {
      return sum[rt];
   }else {
      int m = (l + r) >> 1;
      __int64 ret = 0;
      if (L <= m) {
         ret += query(L, R, LSON);
      }
      if (R > m) {
         ret += query(L, R, RSON);
      }
      return ret;
   }
}


///pku3468(成段增减,区间查询,模板题)
///代码:
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 111111;
long long col[MAXN<<2];      ///lazy标记
long long sum[MAXN<<2];
///把当前节点的信息更新到父节点
void pushUp(int rt) {
   sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
///把当前节点的信息更新到子节点
void pushDown(int rt, int m) {
   if (col[rt]) {
      col[rt<<1] += col[rt];
      col[rt<<1|1] += col[rt];
      sum[rt<<1] += (m - (m >> 1)) * col[rt]; ///更新区间总和
      sum[rt<<1|1] += (m >> 1) * col[rt]; ///更新区间总和
      col[rt] = 0;
   }
}
///建树
void build(int l, int r, int rt) {
   col[rt] = 0;
   if (l == r) {
      scanf("%lld", &sum[rt]);
   }else {
      int m = (l + r) >> 1;
      build(LSON);
      build(RSON);
      pushUp(rt);
   }
}
///区间增减
void update(int L, int R, int val, int l, int r, int rt) {
   if (L <= l && r <= R) {
      col[rt] += val;
      sum[rt] += (r - l + 1) * val;  ///更新区间总和
   }else {
      pushDown(rt, r - l + 1); ///查看该节点是否被标记为lazy,是,则传递lazy标记给子节点
      int m = (l + r) >> 1;
      if (L <= m) {
         update(L, R, val, LSON);
      }
      if (R > m) {
         update(L, R, val, RSON);
      }
      pushUp(rt);
   }
}
///查询区间和
long long query(int L, int R, int l, int r, int rt) {
   if (L <= l && r <= R) {
      return sum[rt];
   }else {
      pushDown(rt, r - l + 1);
      int m = (l + r) >> 1;
      long long ret = 0;
      if (L <= m) {
         ret += query(L, R, LSON);
      }
      if (R > m) {
         ret += query(L, R, RSON);
      }
      return ret;
   }
}


///hdu1698(成段替换,查询整个区间的总和,总和存于根节点)
///代码:
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 111111;
int col[MAXN<<2];      ///lazy标记
int sum[MAXN<<2];
///把当前节点的信息更新到父节点
void pushUp(int rt) {
   sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
///把当前节点的信息更新到子节点
void pushDown(int rt, int m) {
   if (col[rt]) {
      col[rt<<1] = col[rt<<1|1] = col[rt];
      sum[rt<<1] = (m - (m >> 1)) * col[rt];
      sum[rt<<1|1] = (m >> 1) * col[rt];
      col[rt] = 0;
   }
}
///建树
void build(int l, int r, int rt) {
   col[rt] = 0;
   sum[rt] = 1;
   if (l != r) {
      int m = (l + r) >> 1;
      build(LSON);
      build(RSON);
      pushUp(rt);
   }
}
///区间替换
void update(int L, int R, int val, int l, int r, int rt) {
   if (L <= l && r <= R) {
      col[rt] = val;
      sum[rt] = (r - l + 1) * val;
   }else {
      pushDown(rt, r - l + 1); ///查看该父节点是否被标记为lazy,是,则传递lazy标记给子节点
      int m = (l + r) >> 1;
      if (L <= m) {
         update(L, R, val, LSON);
      }
      if (R > m) {
         update(L, R, val, RSON);
      }
      pushUp(rt);
   }
}


///hdu3577(成段增加,查询区间最值)
///代码:
#include<cstdio>
#include<cstring>
#include<climits>
#include<algorithm>
using namespace std;
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 1111111;
const int NN = 1000000;
int col[MAXN<<2];      ///lazy标记
int maxn[MAXN<<2];
///把当前节点的信息更新到父节点
void pushUp(int rt) {
   maxn[rt] = max(maxn[rt<<1], maxn[rt<<1|1]);
}
///把当前节点的信息更新到子节点
void pushDown(int rt) {
   if (col[rt]) {
      col[rt<<1] += col[rt];
      col[rt<<1|1] += col[rt];
      maxn[rt<<1] += col[rt];
      maxn[rt<<1|1] += col[rt];
      col[rt] = 0;
   }
}
///建树(树节点信息为0)
void build(void) {
   memset(col, 0, sizeof(col));
   memset(maxn, 0, sizeof(maxn));
}
///区间增值
void update(int L, int R, int val, int l, int r, int rt) {
   if (L <= l && r <= R) {
      col[rt] += val;
      maxn[rt] += val;
   }else {
      pushDown(rt);   ///查看该节点是否被标记为lazy,是,则传递lazy标记给子节点
      int m = (l + r) >> 1;
      if (L <= m) {
         update(L, R, val, LSON);
      }
      if (R > m) {
         update(L, R, val, RSON);
      }
      pushUp(rt);
   }
}
///查询区间最值
int query(int L, int R, int l, int r, int rt) {
   if (L <= l && r <= R) {
      return maxn[rt];
   }else {
      pushDown(rt);
      int m = (l + r) >> 1;
      int ret1 = INT_MIN;
      int ret2 = INT_MIN;
      if (L <= m) {
         ret1 = query(L, R, LSON);
      }
      if (R > m) {
         ret2 = query(L, R, RSON);
      }
      return (ret1 > ret2 ? ret1 : ret2);
   }
}
int main(void) {
   int T, n, k;

   scanf("%d", &T);
   for (int cas=1; cas<=T; ++cas) {
      scanf("%d%d", &k, &n);
      build();

      int a, b;
      printf("Case %d:\n", cas);
      for (int i=1; i<=n; ++i) {
         scanf("%d%d", &a, &b);
         --b;     ///注意(常识):到目的站时,人下车!所以,区间是[a, b-1]
         if (query(a, b, 1, NN, 1) < k) {
            update(a, b, 1, 1, NN, 1);
            printf("%d ", i);
         }
      }
      printf("\n\n");
   }

   return 0;
}



///hdu1556(成段增加,查询叶子节点最后的总值)
///代码:
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 111111;
int num[MAXN];
int col[MAXN<<2];      ///lazy标记
///把当前节点的信息更新到子节点
void pushDown(int rt) {
   if (col[rt]) {
      col[rt<<1] += col[rt];
      col[rt<<1|1] += col[rt];
      col[rt] = 0;
   }
}
///建树
void build(void) {
   memset(col, 0, sizeof(col));
}
///区间增值
void update(int L, int R, int val, int l, int r, int rt) {
   if (L <= l && r <= R) {
      col[rt] += val;       ///累加延时标记
   }else {
      pushDown(rt);   ///查看该节点是否被标记为lazy,是,则传递lazy标记给子节点
      int m = (l + r) >> 1;
      if (L <= m) {
         update(L, R, val, LSON);
      }
      if (R > m) {
         update(L, R, val, RSON);
      }
   }
}
void query(int l, int r, int rt) {
   if (l == r) {   ///叶子节点总值
      num[l] += col[rt];
   }else {
      pushDown(rt);
      int m = (l + r) >> 1;
      query(LSON);
      query(RSON);
   }
}
int main(void) {
   int n;
   while (scanf("%d", &n) && n != 0) {
      build();
      memset(num, 0, sizeof(num));
      int a, b;
      for (int i=0; i<n; ++i) {
         scanf("%d%d", &a, &b);
         update(a, b, 1, 1, n, 1);
      }
      query(1, n, 1);
      for (int i=1; i<=n; ++i) {
         if (i != 1) {
            printf(" %d", num[i]);
         }else {
            printf("%d", num[i]);
         }
      }
      printf("\n");
   }
   return 0;
}



///pku2777(成段替换,查询区间总类数)
///代码:
#define LSON l, m, rt<<1
#define RSON m+1, r, (rt<<1)|1
const int MAXN = 111111;
const int SIZE = 31;
bool hash[SIZE];
int num[MAXN<<2];
int cnt;
void pushDown(int rt) {
   if (num[rt]) {
      num[rt<<1] = num[rt<<1|1] = num[rt];
      num[rt] = 0;
   }
}
///建树
void build(int l ,int r, int rt) {
   num[rt] = 1;
   if (l != r) {
      int m = (l + r) >> 1;
      build(LSON);
      build(RSON);
   }

}
///区间替换
void update(int L, int R, int val, int l, int r, int rt) {
   if (num[rt] != val) {
      if (L <= l && r <= R) {
         num[rt] = val;
      }else {
         pushDown(rt);   ///查看该节点是否被标记为lazy,是,则传递lazy标记给子节点
         int m = (l + r) >> 1;
         if (L <= m) {
            update(L, R, val, LSON);
         }
         if (R > m) {
            update(L, R, val, RSON);
         }
      }
   }
}
void query(int L, int R, int l, int r, int rt) {
   if (num[rt]) {
      if (!hash[num[rt]]) {
         ++cnt;
         hash[num[rt]] = true;
      }
   }else {
      int m = (l + r) >> 1;
      if (L <= m) {
         query(L, R, LSON);
      }
      if (R > m) {
         query(L, R, RSON);
      }
   }
}

你可能感兴趣的:(线段树,成段更新,单点查询,区间查询,单点更新)