【转载】模板:线段树

感谢勤奋的srf大蒟蒻!!

线段树1

#include <bits/stdc++.h>
#define maxn 100000
#define LL long long 
using namespace std;
inline LL read(){
  LL x = 0,f = 1; char c = getchar();
  while (c < '0' || c > '9') {if (c == '-') f = -1;c = getchar();}
  while (c <='9' && c >='0') {x = x * 10 + c - '0';c = getchar();}
  return x * f;
}

LL n,m,a[maxn+5],f[maxn*8+40],tag[maxn*8+40];

void Build_tree(int note,int x,int y){
  if (x == y) f[note] = a[x],tag[note] = 0;
  else{
    int mid = (x + y) >> 1;
    Build_tree(note * 2, x , mid);
    Build_tree(note * 2 + 1, mid + 1, y);
    f[note] = f[note * 2] + f[note * 2 + 1];
    tag[note] = 0;
  }
}

void downtag(int note,int x,int y){
  if (tag[note] == (LL)0) return;

  int mid = (x + y) >> 1;
  f[note * 2] = f[note * 2] + tag[note] * (mid - x + 1);
  f[note * 2 + 1] = f[note * 2 + 1] + tag[note] * (y - mid);
  tag[note * 2] = tag[note * 2] + tag[note];
  tag[note * 2 + 1] = tag[note * 2 + 1] + tag[note];

  tag[note] = (LL)0;
}

void Add_tree(int note,int x,int y,int ax,int ay,LL k){
  if (ax <= x && ay >= y) f[note] = f[note] + (y - x + 1) * k,tag[note] = tag[note] + k;
  else{
    downtag(note,x,y);
    int mid = (x + y) >> 1;
    if ( ax <= mid ) Add_tree(note * 2 , x , mid , ax , ay , k);
    if ( ay > mid ) Add_tree(note * 2 + 1, mid + 1 , y , ax , ay , k);
    f[note] = f[note * 2] + f[note * 2 + 1];
  }
}

LL Ask_tree(int note,int x,int y,int ax,int ay){
  if (ax <= x && ay >= y) return f[note];
  else{
    downtag(note,x,y);
    int mid = (x + y) >> 1;
    LL Ans = 0; // **数据范围**
    if ( ax <= mid ) Ans = Ans + Ask_tree(note * 2 , x , mid , ax , ay);
    if ( ay > mid ) Ans = Ans + Ask_tree(note * 2 + 1, mid + 1 , y , ax , ay);
    return Ans;
  }
}

int main(){
  n = read(); m = read();
  for (int i = 1; i <= n; ++i) a[i] = read();

  Build_tree(1,1,n);
  while(m--){
    int opt = read(),x = read(),y = read();
      if (opt == 1){
        Add_tree( 1,1,n,x,y,read() );
      }
      else{
        printf("%lld\n",Ask_tree( 1,1,n,x,y ) );
      }
}

  return 0;
}

  

线段树2

#include <bits/stdc++.h>

#define maxn 100000
#define LL long long 
using namespace std;
inline LL read(){
  LL x = 0,f = 1; char c = getchar();
  while (c < '0' || c > '9') {if (c == '-') f = -1;c = getchar();}
  while (c <='9' && c >='0') {x = x * 10 + c - '0';c = getchar();}
  return x * f;
}

LL n,m,a[maxn+5],f[maxn*8+40],taga[maxn*8+40],tagb[maxn*8+40],p;


void Build_tree(int note,int x,int y){
  if (x == y) f[note] = a[x],taga[note] = 1,tagb[note] = 0;
  else{
    int mid = (x + y) >> 1;
    Build_tree(note * 2, x , mid);
    Build_tree(note * 2 + 1, mid + 1, y);
    f[note] = ( f[note * 2] + f[note * 2 + 1] ) % p;
    taga[note] = 1;
    tagb[note] = 0;
    return;
  }
}

void downtag(int note,int x,int y){
  if (taga[note] != 1){//*
    taga[note * 2] = ( taga[note * 2] * taga[note] ) % p;
    tagb[note * 2] = ( tagb[note * 2] * taga[note] ) % p;
    f[note * 2] = ( f[note * 2] * taga[note] ) % p;

    taga[note * 2 + 1] = ( taga[note * 2 + 1] * taga[note] ) % p;
    tagb[note * 2 + 1] = ( tagb[note * 2 + 1] * taga[note] ) % p;
    f[note * 2 + 1] = ( f[note * 2 + 1] * taga[note] ) % p;

    taga[note] = 1;
  }
  if (tagb[note]){//+
    int mid = (x + y) >> 1;

    tagb[note * 2] = ( tagb[note * 2] + tagb[note] ) % p;
    f[note * 2] = ( f[note * 2] + (mid - x + 1) * tagb[note] ) % p;

    tagb[note * 2 + 1] = ( tagb[note * 2 + 1] + tagb[note] ) % p;
    f[note * 2 + 1] = ( f[note * 2 + 1] + (y - mid) * tagb[note] ) % p;

    tagb[note] = 0;
  }
  return;
}

void Add1_tree(int note,int x,int y,int ax,int ay,LL k){ // *
  if (ax <= x && ay >= y) {
    f[note] = (f[note] * k ) % p;
    taga[note] = (taga[note] * k) % p,tagb[note] = (tagb[note] * k) % p;
  }
  else {
    downtag(note,x,y);
    int mid = (x + y) >> 1;
    if (ax <= mid) 
      Add1_tree( note * 2 , x , mid , ax , ay , k);
    if (ay > mid) 
      Add1_tree( note * 2 + 1 , mid + 1 , y , ax , ay , k);
    f[note] = ( f[note * 2] + f[note * 2 + 1] ) % p;
  }
}

void Add2_tree(int note,int x,int y,int ax,int ay,LL k){ // +
  if (ax <= x && ay >= y) 
    f[note] = (f[note] + ( y - x + 1 ) * k ) % p,tagb[note] = (tagb[note] + k) % p;
  else {
    downtag(note,x,y);
    int mid = (x + y) >> 1;
    if (ax <= mid) 
      Add2_tree( note * 2 , x , mid , ax , ay , k);
    if (ay > mid) 
      Add2_tree( note * 2 + 1 , mid + 1 , y , ax , ay , k);
    f[note] = ( f[note * 2] + f[note * 2 + 1] ) % p;
  }
}

LL Ask_tree(int note,int x,int y,int ax,int ay){
  if (ax <= x && ay >= y) return f[note];
  else{
    downtag(note,x,y);
    int mid = (x + y) >> 1;
    LL Ans = 0;     
    if ( ax <= mid ) 
      Ans = Ans + Ask_tree(note * 2 , x , mid , ax , ay),Ans = Ans % p;
    if ( ay > mid ) 
      Ans = Ans + Ask_tree(note * 2 + 1, mid + 1 , y , ax , ay),Ans = Ans % p;
    return Ans;
  }
}

int main(){
  n = read(); m = read(); p = read();
  for (int i = 1; i <= n; ++i) a[i] = read() % p;

  Build_tree(1,1,n);
  while(m--){
    int opt = read(),x = read(),y = read();
    if (opt == 1){
      Add1_tree( 1,1,n,x,y,read() ); // *
    }
    else if (opt == 2){
      Add2_tree( 1,1,n,x,y,read() ); // +
    }
    else{
      printf("%lld\n",Ask_tree( 1,1,n,x,y) );
    }
  }

  return 0;
}

  

posted @ 2017-11-28 18:17  surpassion  阅读(151)  评论(2编辑  收藏  举报