题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1798
思路:这是一道裸的线段树,但是维护标记的时候要小心乘的标记在MOD之后成为0的情况(为此我WA了N次555)
代码:
#include
#include
#define MAXN 100001
struct node {
int l,r;
long long s,M,A;
node (){
M=1;
A=0;
}
} T[MAXN*4];
int a[MAXN];
int n,p,m;
void Build(int l,int r,int t) {
T[t].l=l;
T[t].r=r;
if (l==r) {
T[t].s=a[l]%p;
return ;
}
Build(l,(l+r)>>1,t<<1);
Build(((l+r)>>1)+1,r,(t<<1)^1);
T[t].s=(T[t<<1].s+T[(t<<1)^1].s)%p;
}
void Change(int l,int r,long long k,int t,int flag) {
if (flag==1) {
if (l==T[t].l&&r==T[t].r) {
T[t].M=T[t].M*k;
T[t].M%=p;
if (!T[t].M) T[t].M=p;
T[t].s=T[t].s*k;
T[t].s%=p;
T[t].A=T[t].A*k;
T[t].A%=p;
return ;
}
int mid=(T[t].l+T[t].r)>>1;
if (T[t].M>1) {
Change(T[t].l,mid,T[t].M,t<<1,1);
Change(mid+1,T[t].r,T[t].M,(t<<1)^1,1);
T[t].M=1;
}
if (T[t].A) {
Change(T[t].l,mid,T[t].A,t<<1,2);
Change(mid+1,T[t].r,T[t].A,(t<<1)^1,2);
T[t].A=0;
}
if (r<=mid) Change(l,r,k,t<<1,1)
; else if (l>mid) Change(l,r,k,(t<<1)^1,1)
; else {
Change(l,mid,k,t<<1,1);
Change(mid+1,r,k,(t<<1)^1,1);
}
} else {
if (l==T[t].l&&r==T[t].r) {
long long ret=(r-l+1)*k;
ret%=p;
T[t].s=T[t].s+ret;
T[t].s%=p;
T[t].A=T[t].A+k;
T[t].A%=p;
return ;
}
int mid=(T[t].l+T[t].r)>>1;
if (T[t].M>1) {
Change(T[t].l,mid,T[t].M,t<<1,1);
Change(mid+1,T[t].r,T[t].M,(t<<1)^1,1);
T[t].M=1;
}
if (T[t].A) {
Change(T[t].l,mid,T[t].A,t<<1,2);
Change(mid+1,T[t].r,T[t].A,(t<<1)^1,2);
T[t].A=0;
}
if (r<=mid) Change(l,r,k,t<<1,2)
; else if (l>mid) Change(l,r,k,(t<<1)^1,2)
; else {
Change(l,mid,k,t<<1,2);
Change(mid+1,r,k,(t<<1)^1,2);
}
}
T[t].s=(T[t<<1].s+T[(t<<1)^1].s);
T[t].s%=p;
}
long long Sum(int l,int r,int t) {
if (l==T[t].l&&r==T[t].r) return T[t].s;
int mid=(T[t].l+T[t].r)>>1;
long long rec;
if (r<=mid) rec=Sum(l,r,t<<1)
; else if (l>mid) rec=Sum(l,r,(t<<1)^1)
; else rec=(Sum(l,mid,t<<1)+Sum(mid+1,r,(t<<1)^1)),rec%=p;
rec=(rec*T[t].M);
rec%=p;
long long ret=T[t].A*(r-l+1);
rec=(rec+ret);
rec%=p;
return rec;
}
int main() {
scanf("%d%d",&n,&p);
for (int i=0;i++