线段树
标签(空格分隔): @zhshh 线段树
双标记模板
为什么会有这个?
因为如果看了最后面的代码,会发现有很多用到了(root<<1)+1
等等的结构
而C++的#define
恰好可以方便的解决
定义列表
cnt 当前树
lt 左子树
rt 右子树
lr 左子树的下标
rr 右子树的下标
ci const int
LL long long
#include <iostream>
#include <cstdio>
#include <algorithm>
#define cnt tree[root]
#define lr (root<<1)
#define rr ((root<<1)+1)
#define lt tree[lr]
#define rt tree[rr]
#define ci const int
#define MAX (100000+10)
#define LL long long
using namespace std;
struct node{
int left,right;
LL add,mul,val;
node(){
mul=1;
add=0;
}
}tree[MAX<<2];
LL a[MAX];
int n;
LL mod;
void pushup(ci root){
cnt.val=lt.val+rt.val;
}
void pushdown(ci root){
if(cnt.mul!=1 || cnt.add!=0){
lt.val=(lt.val*cnt.mul)%mod;
lt.val=(lt.val+cnt.add*(lt.right-lt.left+1))%mod;
lt.add=(lt.add*cnt.mul)%mod;
lt.add=(lt.add+cnt.add)%mod;
lt.mul=(lt.mul*cnt.mul)%mod;
rt.val=(rt.val*cnt.mul)%mod;
rt.val=(rt.val+cnt.add*(rt.right-rt.left+1))%mod;
rt.add=(rt.add*cnt.mul)%mod;
rt.add=(rt.add+cnt.add)%mod;
rt.mul=(rt.mul*cnt.mul)%mod;
cnt.mul=1;
cnt.add=0;
}
}
void mul(ci root,ci left,ci right,ci k){
if(left<=cnt.left && right>=cnt.right){
cnt.mul=(cnt.mul*k)%mod;
cnt.add=(cnt.add*k)%mod;
cnt.val=(cnt.val*k)%mod;
return ;
}
pushdown(root);
int mid=(cnt.left+cnt.right)>>1;
if(left<=mid)mul(lr,left,right,k);
if(right>mid)mul(rr,left,right,k);
pushup(root);
}
void add(ci root,ci left,ci right,ci c){
if(left<=cnt.left && right>=cnt.right){
cnt.add=(cnt.add+c)%mod;
cnt.val=(cnt.val+c*(cnt.right-cnt.left+1))%mod;
return ;
}
pushdown(root);
int mid=(cnt.left+cnt.right)>>1;
if(left<=mid)add(lr,left,right,c);
if(right>mid)add(rr,left,right,c);
pushup(root);
return ;
}
LL query(ci root,ci left,ci right){
if(left<=cnt.left && right>=cnt.right){
return cnt.val;
}
pushdown(root);
int mid=(cnt.left+cnt.right)>>1;
LL ans=0;
if(left<=mid)ans=(ans+query(lr,left,right))%mod;
if(right>mid)ans=(ans+query(rr,left,right))%mod;
return ans;
}
void build(ci root,ci left,ci right){
cnt.left=left;
cnt.right=right;
if(left==right){
cnt.val=a[left];
return ;
}
int mid=(cnt.left+cnt.right)>>1;
build(lr,left,mid);
build(rr,mid+1,right);
pushup(root);
return ;
}
void pr(){
for(int i=1;i<=n;i++){
printf("%3d%7d\n",i,query(1,i,i));
}
cout<<endl;
}
int main(){
// freopen("in.txt","r",stdin);
int m,t1,t2,t3;
cin>>n>>m>>mod;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]%=mod;
}
build(1,1,n);
for(int i=1;i<=m;i++){
cin>>t1;
if(t1==1){
cin>>t1>>t2>>t3;
mul(1,t1,t2,t3);
}else{
if(t1==2){
cin>>t1>>t2>>t3;
add(1,t1,t2,t3);
}else{
cin>>t1>>t2;
cout<<query(1,t1,t2)<<endl;
}
}
}
pr();
}
单标记
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 100000+10
using namespace std;
int n, m;
struct node {
int left, right;
long long x, mark;
} tree[MAX<<2];
int a [MAX];
void pushup(int root)
{
tree[root].x = tree[root * 2].x + tree[root * 2 + 1].x;
}
void pushdown(int root,int d)
{
if (tree[root].mark) {
tree[root * 2].x += tree[root].mark*(d-d/2);
tree[root * 2 + 1].x += tree[root].mark*(d/2);
tree[root * 2].mark += tree[root].mark;
tree[root * 2 + 1].mark += tree[root].mark;
tree[root].mark = 0;
}
}
void update(int left, int right, int c, int root)
{
if (left <= tree[root].left && right >= tree[root].right) {
tree[root].mark += c;
tree[root].x += (tree[root].right - tree[root].left + 1) * c;
return;
}
pushdown(root, tree[root].right - tree[root].left + 1);
int mid = (tree[root].left + tree[root].right) / 2;
if (left <= mid)
update(left, right, c, root * 2);
if (right > mid)
update(left, right, c, root * 2 + 1);
pushup(root);
}
long long query(int left, int right, int root)
{
if (left <= tree[root].left && right >= tree[root].right)
return tree[root].x;
pushdown(root, tree[root].right - tree[root].left + 1);
int mid = (tree[root].left + tree[root].right) / 2;
long long ans = 0;
if (left <= mid)
ans += query(left, right, root * 2);
if (right > mid)
ans += query(left, right, 2 * root + 1);
return ans;
}
void build (int root,int left,int right)
{
tree[root].left=left;
tree[root].right=right;
if(left==right) {
tree[root].x=a[left];
} else {
int mid=(left+right)/2;
build(2*root,left,mid);
build(2*root+1,mid+1,right);
tree[root].x=tree[2*root].x+tree[2*root+1].x;
}
}
int main()
{
// freopen("al1.txt","r",stdin);
cin>>n>>m;
for(int i=1; i<=n; i++)cin>>a[i];
build(1,1,n);
int ope;
int q1,q2,q3;
for(int qwe=1; qwe<=m; qwe++) {
// for(int i=1;i<=n;i++)cout<<query(i,i,1)<<"~";
// cout<<endl;
cin>>ope;
if(ope==1) {
cin>>q1>>q2>>q3;
update(q1,q2,q3,1);
} else {
cin>>q1>>q2;
cout<<query(q1,q2,1);
cout<<endl;
}
}
}
双标记
#include <iostream>
#include <cstdio>
#define LL unsigned long long
#define MAX 100010
using namespace std;
struct node {
int left,right;
LL add,mul,val;
node(){
mul=1;
add=0;
}
}tree[MAX<<2];
LL a[MAX];
int n;
LL mod;
void pushup(const int root){
tree[root].val=(tree[root*2].val+tree[root*2+1].val);
}
void pushdown(const int root){
if(tree[root].mul!=1 || tree[root].add!=0){
tree[root<<1].val=(tree[root<<1].val*tree[root].mul)%mod;
tree[root<<1].val=(tree[root<<1].val+tree[root].add*(tree[root<<1].right-tree[root<<1].left+1))%mod;
tree[root<<1].add=(tree[root<<1].add*tree[root].mul)%mod;
tree[root<<1].add=(tree[root<<1].add+tree[root].add)%mod;
tree[root<<1].mul=(tree[root<<1].mul*tree[root].mul)%mod;
tree[(root<<1)+1].val=(tree[(root<<1)+1].val*tree[root].mul)%mod;
tree[(root<<1)+1].val=(tree[(root<<1)+1].val+tree[root].add*(tree[(root<<1)+1].right-tree[(root<<1)+1].left+1))%mod;
tree[(root<<1)+1].add=(tree[(root<<1)+1].add*tree[root].mul)%mod;
tree[(root<<1)+1].add=(tree[(root<<1)+1].add+tree[root].add)%mod;
tree[(root<<1)+1].mul=(tree[(root<<1)+1].mul*tree[root].mul)%mod;
tree[root].mul=1;
tree[root].add=0;
}
}
void add(const int root,const int left,const int right, const int c){
if(left<=tree[root].left && right>=tree[root].right){
tree[root].add=(tree[root].add+c)%mod;
tree[root].val=(tree[root].val+c*(tree[root].right-tree[root].left+1))%mod;
return ;
}
pushdown(root);
int mid=(tree[root].left+tree[root].right)/2;
if(left<=mid)add(root*2,left,right,c);
if(right>mid)add(root*2+1,left,right,c);
pushup(root);
return ;
}
void mul(const int root,const int left,const int right,const int k){
if(left<=tree[root].left && right>=tree[root].right){
tree[root].mul=(tree[root].mul*k)%mod;
tree[root].add=(tree[root].add*k)%mod;
tree[root].val=(tree[root].val*k)%mod;
return ;
}
pushdown(root);
int mid=(tree[root].left+tree[root].right)/2;
if(left<=mid)mul(root*2,left,right,k);
if(right>mid)mul(root*2+1,left,right,k);
pushup(root);
return ;
}
int query(const int root,const int left,const int right){
if(left<=tree[root].left && right>=tree[root].right){
return tree[root].val;
}
pushdown(root);
int mid=(tree[root].left+tree[root].right)/2;
LL ans=0;
if(left<=mid)ans=(ans+query(root*2,left,right))%mod;
if(right>mid)ans=(ans+query(root*2+1,left,right))%mod;
return ans;
}
void build(const int root,const int left,const int right){
tree[root].left=left;
tree[root].right=right;
if(left==right){
tree[root].val=a[left];
return ;
}
int mid=(tree[root].left+tree[root].right)/2;
build(root*2,left,mid);
build(root*2+1,mid+1,right);
pushup(root);
return ;
}
void pr(){
for(int i=1;i<=n;i++){
cout<<query(1,i,i)<<endl;
}
cout<<endl;
}
int main(){
int m,t1,t2,t3;
cin>>n>>m>>mod;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]%=mod;
}
build(1,1,n);
for(int i=1;i<=m;i++){
cin>>t1;
if(t1==1){
cin>>t1>>t2>>t3;
mul(1,t1,t2,t3);
}else{
if(t1==2){
cin>>t1>>t2>>t3;
add(1,t1,t2,t3);
}else{
cin>>t1>>t2;
cout<<query(1,t1,t2)<<endl;
}
}
}
}