题目传送门
题目大意
含n个数字的的数列a各数字初值均为0,对其进行m次操作,每次操作可为下列之一:
1
x
y
c
1\ x\ y\ c
1 x y c:
a
x
a_x
ax到
a
y
a_y
ay间的数字(含边界)均增加c
2
x
y
c
2\ x\ y\ c
2 x y c:
a
x
a_x
ax到
a
y
a_y
ay间的数字(含边界)均乘以c
3
x
y
c
3\ x\ y\ c
3 x y c:
a
x
a_x
ax到
a
y
a_y
ay间的数字(含边界)均变为c
4
x
y
p
4\ x\ y\ p
4 x y p:输出
a
x
a_x
ax到
a
y
a_y
ay间的数字(含边界)的p次方之和
对于每个操作4,输出答案模10007
数据组数<=10。
1
<
=
n
,
m
<
=
1
e
5
,
1
<
=
x
<
=
y
<
=
n
1<=n,m<=1e5,1<=x<=y<=n
1<=n,m<=1e5,1<=x<=y<=n
1
<
=
c
<
=
1
e
4
,
1
<
=
p
<
=
3
1<=c<=1e4,1<=p<=3
1<=c<=1e4,1<=p<=3
输入 0 0结束
思路
显然线段树,区间修改,区间查询
麻烦就在查询的地方为p次方之和,但是
1
<
=
p
<
=
3
1<=p<=3
1<=p<=3,所以我们可以选择分别维护p的一次方,二次方,三次方的和
lazy标记也相应的标记,修改,乘,加
lazy标记下传的时候的顺序显然应该是
1、修改,然后将乘法标记变成1,加法标记变成0
2、乘
3、加
三个次方的维护为:
s
u
m
1
=
x
1
+
x
2
+
.
.
.
+
x
n
sum1 = x_1 +x_2 + ...+ x_n
sum1=x1+x2+...+xn
s
u
m
2
=
x
1
2
+
x
2
2
+
.
.
.
+
x
n
2
sum2 = x_1^2 +x_2^2 + ... +x_n^2
sum2=x12+x22+...+xn2
s
u
m
3
=
x
1
3
+
x
2
3
+
.
.
.
+
x
n
3
sum3 = x_1^3 + x_2^3 + ... + x_n^3
sum3=x13+x23+...+xn3
进行相应操作时的变化
加:
s
u
m
1
=
(
x
1
+
k
)
+
(
x
2
+
k
)
+
.
.
.
+
(
x
n
+
k
)
=
s
u
m
1
+
n
k
sum1=(x_1 +k) +(x_2 +k) + ...+(x_n + k)= sum1 + nk
sum1=(x1+k)+(x2+k)+...+(xn+k)=sum1+nk
s
u
m
2
=
(
x
1
+
k
)
2
+
(
x
2
+
k
)
2
+
.
.
.
+
(
x
n
+
k
)
2
=
s
u
m
2
+
2
k
∗
s
u
m
1
+
n
k
2
sum2=(x_1 + k)^2 +(x_2 +k)^2 +...+(x_n + k)^2= sum2 + 2k*sum1 + nk^2
sum2=(x1+k)2+(x2+k)2+...+(xn+k)2=sum2+2k∗sum1+nk2
s
u
m
3
=
(
x
1
+
k
)
3
+
(
x
2
+
k
)
3
+
.
.
.
+
(
x
n
+
k
)
3
=
s
u
m
3
+
n
k
3
+
3
k
∗
s
u
m
2
+
3
∗
k
2
s
u
m
1
sum3=(x_1 +k)^3 +(x_2 +k)^3 + ...+(x_n + k)^3=sum3 + nk^3 + 3k*sum2 + 3*k^2sum1
sum3=(x1+k)3+(x2+k)3+...+(xn+k)3=sum3+nk3+3k∗sum2+3∗k2sum1
乘:
s
u
m
1
=
s
u
m
1
∗
k
sum1= sum1 * k
sum1=sum1∗k
s
u
m
2
=
s
u
m
2
∗
k
2
sum2 = sum2 * k^2
sum2=sum2∗k2
s
u
m
3
=
s
u
m
3
∗
k
3
sum3= sum3 * k^3
sum3=sum3∗k3
修改:
s
u
m
1
=
n
k
sum1= nk
sum1=nk
s
u
m
2
=
n
∗
k
2
sum2=n*k^2
sum2=n∗k2
s
u
m
3
=
n
∗
k
3
sum3=n* k^3
sum3=n∗k3
AC Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define debug(a) cout<<#a<<"="<<a<<endl;
#define INF 0x3f3f3f3f
const int M=10007;
const int N=1e5 +9;
int n, m , c, x, y, v;
struct segtree{
int s1, s2, s3;
int lazya, lazym, lazyc;
void clear(){
s1=s2=s3=0;
lazya=lazyc=0;
lazym=1;
}
}tr[N<<2];
inline int lc(int p) {return p<<1;}
inline int rc(int p) {return p<<1|1;}
inline void push_up(int p){
tr[p].s1=(tr[lc(p)].s1+tr[rc(p)].s1)%M;
tr[p].s2=(tr[lc(p)].s2+tr[rc(p)].s2)%M;
tr[p].s3=(tr[lc(p)].s3+tr[rc(p)].s3)%M;
}
inline void build(int p, int l, int r){
tr[p].clear();
if(l==r) return ;
int mid=(l+r)>>1;
build(lc(p), l, mid);
build(rc(p), mid+1, r);
}
inline void f(int f, int p, int len){
int k;
if(tr[f].lazyc){
k=tr[f].lazyc;
tr[p].s3=len*k*k*k%M;
tr[p].s2=len*k*k%M;
tr[p].s1=len*k%M;
tr[p].lazya=0;
tr[p].lazym=1;
tr[p].lazyc=k;
}
if(tr[f].lazym!=1){
k=tr[f].lazym;
tr[p].s3=k*k*k*tr[p].s3%M;
tr[p].s2=k*k*tr[p].s2%M;
tr[p].s1=k*tr[p].s1%M;
tr[p].lazya=k*tr[p].lazya%M;
tr[p].lazym=k*tr[p].lazym%M;
}
if(tr[f].lazya){
k=tr[f].lazya;
tr[p].s3=(tr[p].s3 + len*k*k*k + 3*k*tr[p].s2 + 3*k*k*tr[p].s1)%M;
tr[p].s2=(tr[p].s2 + len*k*k + 2*k*tr[p].s1)%M;
tr[p].s1=(tr[p].s1 + len*k)%M;
tr[p].lazya=(tr[p].lazya + k)%M;
}
}
inline void push_down(int p, int lenl, int lenr){
f(p, lc(p), lenl);
f(p, rc(p), lenr);
tr[p].lazya=tr[p].lazyc=0;
tr[p].lazym=1;
}
inline void updata(int p, int l, int r, int x, int y, int k){
if(l<=x && y<=r){
int len=y-x+1;
if(c==1){
tr[p].lazya=(tr[p].lazya+k)%M;
tr[p].s3=(tr[p].s3 + len*k*k*k + 3*k*tr[p].s2 + 3*k*k*tr[p].s1)%M;
tr[p].s2=(tr[p].s2 + 2*k*tr[p].s1 + len*k*k)%M;
tr[p].s1=(tr[p].s1 + len*k)%M;
}
else if(c==2){
tr[p].lazya=tr[p].lazya*k%M;
tr[p].lazym=tr[p].lazym*k%M;
tr[p].s3=k*k*k*tr[p].s3%M;
tr[p].s2=k*k*tr[p].s2%M;
tr[p].s1=k*tr[p].s1%M;
}
else{
tr[p].lazyc=k;
tr[p].lazya=0;
tr[p].lazym=1;
tr[p].s3=len*k*k*k%M;
tr[p].s2=len*k*k%M;
tr[p].s1=len*k%M;
}
return ;
}
int mid=(x+y)>>1;
push_down(p, mid-x+1, y-mid);
if(l<=mid) updata(lc(p), l, r, x, mid, k);
if(r>mid) updata(rc(p), l, r, mid+1, y, k);
push_up(p);
}
inline int query(int p, int l, int r, int x, int y){
if(l<=x && y<=r){
if(v==1) return tr[p].s1;
else if(v==2) return tr[p].s2;
else return tr[p].s3;
}
int mid=(x+y)>>1;
push_down(p, mid-x+1, y-mid);
int ans=0;
if(l<=mid) ans=(ans+query(lc(p), l, r, x, mid))%M;
if(r>mid) ans=(ans+query(rc(p), l, r, mid+1, y))%M;
return ans;
}
signed main(){
while(~scanf("%lld%lld", &n, &m)&&(n||m)){
build(1,1,n);
for(int i=1; i<=m; i++){
scanf("%lld%lld%lld%lld", &c, &x, &y, &v);
if(c==4) printf("%lld\n", query(1,x,y,1,n));
else updata(1,x,y,1,n,v);
}
}
return 0;
}