标签:线段树
传送门:BZOJ1798
双状态的线段树,注意优先级。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct Node{
int ls,rs;
long long w;
long long add;
long long times;
Node(){
ls=rs=0;
w=0;
add=0;
times=1;
}
};
long long p;
Node tree[200005];
int y1,y2;
int root,num;
int da[100005];
int m,n;
void PushDown(int root)
{
tree[tree[root].ls].add=tree[tree[root].ls].add*tree[root].times+tree[root].add;
tree[tree[root].rs].add=tree[tree[root].rs].add*tree[root].times+tree[root].add;
tree[tree[root].ls].times*=tree[root].times;
tree[tree[root].rs].times*=tree[root].times;
tree[tree[root].ls].add%=p;
tree[tree[root].rs].add%=p;
tree[tree[root].ls].times%=p;
tree[tree[root].rs].times%=p;
tree[root].times=1;tree[root].add=0;
}
void Maintain(int root,int l,int r)
{
tree[root].w=tree[tree[root].ls].w+tree[tree[root].rs].w;
tree[root].w*=tree[root].times;
tree[root].w+=(r-l+1)*tree[root].add;
tree[root].w%=p;
}
void Update(int root,int l,int r,int addv,int timesv)
{
if(y1<=l&&r<=y2){
if(addv!=-1)
tree[root].add+=addv;
else{
tree[root].add*=timesv;
tree[root].times*=timesv;
}
tree[root].add%=p;
tree[root].times%=p;
}
else{
PushDown(root);
int mid=(l+r)/2;
if(y1<=mid)
Update(tree[root].ls,l,mid,addv,timesv);
else
Maintain(tree[root].ls,l,mid);
if(mid<y2)
Update(tree[root].rs,mid+1,r,addv,timesv);
else
Maintain(tree[root].rs,mid+1,r);
}
Maintain(root,l,r);
}
long long Query(int root,int l,int r)
{
if(y1<=l&&r<=y2)
return tree[root].w%p;
int mid=(l+r)/2;
PushDown(root);
Maintain(tree[root].ls,l,mid);
Maintain(tree[root].rs,mid+1,r);
Maintain(root,l,r);
long long ans=0;
if(y1<=mid)
ans+=Query(tree[root].ls,l,mid);
if(mid<y2)
ans+=Query(tree[root].rs,mid+1,r);
return ans%p;
}
void MakeTree(int&root,int l,int r)
{
root=++num;
if(l==r)
return;
int mid=(l+r)/2;
MakeTree(tree[root].ls,l,mid);
MakeTree(tree[root].rs,mid+1,r);
}
void Readdata()
{
scanf("%d",&n);
cin>>p;
for(int i=1;i<=n;i++)
scanf("%d",&da[i]);
}
void Solve()
{
for(int i=1;i<=n;i++){
y1=y2=i;
Update(root,1,n,da[i],1);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int a,t,g,c;
scanf("%d",&a);
if(a==1){
scanf("%d%d%d",&y1,&y2,&c);
Update(root,1,n,-1,c);
}
if(a==2){
scanf("%d%d%d",&y1,&y2,&c);
Update(root,1,n,c,1);
}
if(a==3){
scanf("%d%d",&y1,&y2);
printf("%lld\n",Query(root,1,n));
}
}
}
int main()
{
Readdata();
MakeTree(root,1,n);
Solve();
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:线段树
原文地址:http://blog.csdn.net/le_ballon_rouge/article/details/47731791