hdu4578 Transformation【线段树】
Yuanfang is puzzled with the question below:
There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y.
Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him.
Input
There are no more than 10 test cases.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
Output
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
Sample Input
5 5 3 3 5 7 1 2 4 4 4 1 5 2 2 2 5 8 4 3 5 3 0 0
Sample Output
307 7489
超麻烦的线段树 一共四种操作
加 乘 赋值 幂
分别用一个数组表示
关键在于下方pushdown的操作
赋值的时候就直接下放 保存的幂也直接求
加和乘的操作一起下放 用平方和立方公式来求sum
自己写的不知道为什么RE了 查了半天查不出来 而且好复杂懒得查了.....
下面是题解的代码
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 110000
#define lmin 1
#define rmax n
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define root lmin,rmax,1
#define now l,r,rt
#define int_now int l,int r,int rt
#define INF 99999999
#define LL int
#define mod 10007
LL add[maxn*4];
LL mul[maxn*4];
LL num[maxn*4];
LL sum[maxn*4][4];
void push_up(int_now)
{
for(int i=1; i<=3; i++)
sum[rt][i]=(sum[rt<<1][i]+sum[rt<<1|1][i])%mod;
}
void push_down(int_now)
{
if(l==r)return;
int ll=(r+l)/2-l+1;
int rr=r-(r+l)/2;
if(num[rt] != 0)
{
num[rt<<1] = num[rt<<1|1] = num[rt];
add[rt<<1] = add[rt<<1|1] = 0;
mul[rt<<1] = mul[rt<<1|1] = 1;
sum[rt<<1][1] = (ll)*num[rt<<1]%mod;
sum[rt<<1][2] = (ll)*num[rt<<1]%mod*num[rt<<1]%mod;
sum[rt<<1][3] = (ll)*num[rt<<1]%mod*num[rt<<1]%mod*num[rt<<1]%mod;
sum[(rt<<1)|1][1] = (rr)*num[rt<<1|1]%mod;
sum[(rt<<1)|1][2] = (rr)*num[rt<<1|1]%mod*num[rt<<1|1]%mod;
sum[(rt<<1)|1][3] = (rr)*num[rt<<1|1]%mod*num[rt<<1|1]%mod*num[rt<<1|1]%mod;
num[rt] = 0;
}
if(add[rt] != 0 || mul[rt] != 1)
{
add[rt<<1] = ( mul[rt]*add[rt<<1]%mod + add[rt] )%mod;
mul[rt<<1] = mul[rt<<1]*mul[rt]%mod;
int sum1,sum2,sum3;
sum1 = (sum[rt<<1][1]*mul[rt]%mod + (ll)*add[rt]%mod)%mod;
sum2 = (mul[rt] * mul[rt] % mod * sum[rt<<1][2] % mod + 2*add[rt]*mul[rt]%mod * sum[rt<<1][1]%mod + (ll)*add[rt]%mod*add[rt]%mod)%mod;
sum3 = mul[rt] * mul[rt] % mod * mul[rt] % mod * sum[rt<<1][3] % mod;
sum3 = (sum3 + 3*mul[rt] % mod * mul[rt] % mod * add[rt] % mod * sum[rt<<1][2]) % mod;
sum3 = (sum3 + 3*mul[rt] % mod * add[rt] % mod * add[rt] % mod * sum[rt<<1][1]) % mod;
sum3 = (sum3 + (ll)*add[rt]%mod * add[rt] % mod * add[rt] % mod) % mod;
sum[rt<<1][1] = sum1;
sum[rt<<1][2] = sum2;
sum[rt<<1][3] = sum3;
add[rt<<1|1] = ( mul[rt]*add[rt<<1|1]%mod + add[rt] )%mod;
mul[rt<<1|1] = mul[rt<<1|1] * mul[rt] % mod;
sum1 = (sum[(rt<<1)|1][1]*mul[rt]%mod + (rr)*add[rt]%mod)%mod;
sum2 = (mul[rt] * mul[rt] % mod * sum[(rt<<1)|1][2] % mod + 2*add[rt]*mul[rt]%mod * sum[(rt<<1)|1][1]%mod + (rr)*add[rt]%mod*add[rt]%mod)%mod;
sum3 = mul[rt] * mul[rt] % mod * mul[rt] % mod * sum[(rt<<1)|1][3] % mod;
sum3 = (sum3 + 3*mul[rt] % mod * mul[rt] % mod * add[rt] % mod * sum[(rt<<1)|1][2]) % mod;
sum3 = (sum3 + 3*mul[rt] % mod * add[rt] % mod * add[rt] % mod * sum[(rt<<1)|1][1]) % mod;
sum3 = (sum3 + (rr)*add[rt]%mod * add[rt] % mod * add[rt] % mod) % mod;
sum[(rt<<1)|1][1] = sum1;
sum[(rt<<1)|1][2] = sum2;
sum[(rt<<1)|1][3] = sum3;
add[rt] = 0;
mul[rt] = 1;
}
}
void creat(int_now)
{
add[rt]=0;
mul[rt]=1;
num[rt]=0;
for(int i=1; i<=3; i++)sum[rt][i]=0;
if(l!=r)
{
creat(lson);
creat(rson);
}
}
void update(int ll,int rr,int x,int k,int_now)
{
if(ll>r||rr<l)return;
if(ll<=l&&rr>=r)
{
x=x%mod;
if(k==1)
{
add[rt]=(add[rt]+x)%mod;
sum[rt][3]=(sum[rt][3]+3*sum[rt][2]%mod*x%mod+3*sum[rt][1]%mod*x%mod*x%mod+x*x%mod*x%mod*(r-l+1)%mod)%mod;
sum[rt][2]=(sum[rt][2]+(r-l+1)*x%mod*x%mod+2*x%mod*sum[rt][1]%mod)%mod;
sum[rt][1]=(sum[rt][1]+x*(r-l+1)%mod)%mod;
}
else if(k==2)
{
mul[rt]=(mul[rt]*x)%mod;
add[rt]=(add[rt]*x)%mod;
for(int i=1; i<=3; i++)
{
int j=i;
LL ans=1;
while(j--)ans=(ans*x)%mod;
sum[rt][i]=(sum[rt][i]*ans)%mod;
}
}
else
{
num[rt]=x;
mul[rt]=1;
add[rt]=0;
for(int i=1; i<=3; i++)
{
int j=i;
LL ans=1;
while(j--)ans=(ans*x)%mod;
sum[rt][i]=(ans*(r-l+1)%mod)%mod;
}
}
return;
}
push_down(now);
update(ll,rr,x,k,lson);
update(ll,rr,x,k,rson);
push_up(now);
}
LL query(int ll,int rr,int p,int_now)
{
if(ll>r||rr<l)return 0;
if(ll<=l&&rr>=r)
{
return sum[rt][p];
}
push_down(now);
return (query(ll,rr,p,lson)+query(ll,rr,p,rson))%mod;
}
int main()
{
int n,m,k,a,b,c;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
creat(root);
while(m--)
{
scanf("%d%d%d%d",&k,&a,&b,&c);
if(k<=3)
{
update(a,b,c,k,root);
}
else
{
printf("%d\n",query(a,b,c,root));
}
}
}
return 0;
}
RE的代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
#define inf 1e18
using namespace std;
const int maxn = 110005;
const int mod = 10007;
int m, n;
long long sum[maxn << 2][4], lazyadd[maxn<<2], lazymul[maxn<<2], lazynum[maxn<<2];
void pushup(int rt)
{
for(int i = 1; i <= 3; i++){
sum[rt][i] = (sum[rt << 1][i] + sum[rt << 1|1][i]) % mod;
}
}
void build(int l, int r, int rt)
{
lazyadd[rt] = 0;
lazymul[rt] = 1;
lazynum[rt] = 0;
for(int i = 1; i <= 3; i++)
sum[rt][i] = 0;
if(l == r) return;
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
}
void pushdown(int l, int r, int rt)
{
if(l == r) return;
int m = (l + r) / 2;
int lnum = m - l + 1, rnum = r - m;
if(lazynum[rt]){//ж╠╫соб╥е
lazynum[rt << 1] = lazynum[rt<<1|1] = lazynum[rt];
lazyadd[rt<<1] = lazyadd[rt<<1|1] = 0;
lazymul[rt<<1] = lazymul[rt<<1|1] = 1;
sum[rt<<1][1] = lnum * lazynum[rt<<1] % mod;
sum[rt<<1][2] = lnum * lazynum[rt<<1] % mod * lazynum[rt<<1] % mod;
sum[rt<<1][3] = lnum * lazynum[rt<<1] % mod * lazynum[rt<<1] % mod * lazynum[rt<<1] % mod;
sum[rt<<1|1][1] = rnum * lazynum[rt<<1|1] % mod;
sum[rt<<1|1][2] = rnum * lazynum[rt<<1|1] % mod * lazynum[rt<<1|1] % mod;
sum[rt<<1|1][3] = rnum * lazynum[rt<<1|1] % mod * lazynum[rt<<1|1] % mod * lazynum[rt<<1|1] % mod;
lazynum[rt] = 0;
}
if(lazyadd[rt] || lazymul[rt] != 1){
lazyadd[rt<<1] = (lazymul[rt] * lazyadd[rt<<1] % mod + lazyadd[rt])% mod;
lazymul[rt<<1] = lazymul[rt] * lazymul[rt<<1] % mod;
int sum1 = (sum[rt<<1][1] * lazymul[rt] % mod + lnum * lazyadd[rt] % mod) % mod;
int sum2 = (sum[rt<<1][2] * lazymul[rt] % mod * lazymul[rt] % mod + 2 * lazyadd[rt] * lazymul[rt] % mod * sum[rt<<1][1] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
int sum3 = (sum[rt<<1][3] * lazymul[rt] % mod * lazymul[rt] % mod * lazymul[rt] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
sum3 = (sum3 + 3 * lazymul[rt] * lazyadd[rt] % mod * lazyadd[rt] % mod * sum[rt<<1][1] % mod) % mod;
sum3 = (sum3 + 3 * lazymul[rt] * lazymul[rt] % mod * lazyadd[rt] % mod * sum[rt<<1][2] % mod) % mod;
sum[rt<<1][1] = sum1;
sum[rt<<1][2] = sum2;
sum[rt<<1][3] = sum3;
lazyadd[rt<<1|1] = (lazymul[rt] * lazyadd[rt<<1|1] % mod + lazyadd[rt]) % mod;
lazymul[rt<<1|1] = lazymul[rt] * lazymul[rt<<1|1] % mod;
sum1 = (sum[rt<<1|1][1] * lazymul[rt] % mod + lnum * lazyadd[rt] % mod) % mod;
sum2 = (sum[rt<<1|1][2] * lazymul[rt] % mod * lazymul[rt] % mod + 2 * lazyadd[rt] * lazymul[rt] % mod * sum[rt<<1|1][1] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
sum3 = (sum[rt<<1|1][3] * lazymul[rt] % mod * lazymul[rt] % mod * lazymul[rt] % mod + lnum * lazyadd[rt] % mod * lazyadd[rt] % mod * lazyadd[rt] % mod) % mod;
sum3 = (sum3 + 3 * lazymul[rt] * lazyadd[rt] % mod * lazyadd[rt] % mod * sum[rt<<1|1][1] % mod) % mod;
sum3 = (sum3 + 3 * lazymul[rt] * lazymul[rt] % mod * lazyadd[rt] % mod * sum[rt<<1|1][2] % mod) % mod;
sum[rt<<1|1][1] = sum1;
sum[rt<<1|1][2] = sum2;
sum[rt<<1|1][3] = sum3;
lazyadd[rt] = 0;
lazymul[rt] = 1;
}
}
void update(int L, int R, int x, int k, int l, int r, int rt)
{
if(L > r || R < l)return;
if(L <= l && R >= r){
x = x % mod;
if(k == 1){
lazyadd[rt] = (lazyadd[rt] + x) % mod;
sum[rt][3] = (sum[rt][3] + 3 * sum[rt][2] % mod * x % mod + 3 * sum[rt][1] % mod * x % mod * x % mod + (r - l + 1) * x % mod * x % mod * x % mod) % mod;
sum[rt][2] = (sum[rt][2] + 2 * sum[rt][1] % mod * x % mod + (r - l + 1) * x % mod * x % mod) % mod;
sum[rt][1] = (sum[rt][1] + (r - l + 1) * x % mod) % mod;
}
else if(k == 2){
lazymul[rt] = lazymul[rt] * x % mod;
lazyadd[rt] = lazyadd[rt] * x % mod;
for(int i = 1; i <= 3; i++){
int j = i;
long long ans = 1;
while(j--){
ans = (ans * x) % mod;
}
sum[rt][i] = (sum[rt][i] * ans) % mod;
}
}
else{
lazynum[rt] = x;
lazymul[rt] = 1;
lazyadd[rt] = 0;
for(int i = 1; i <= 3; i++){
int j = i;
long long ans = 1;
while(j--){
ans = (ans * x) % mod;
}
sum[rt][i] = (ans * (r - l + 1) % mod) % mod;
}
}
return;
}
pushdown(l, r, rt);
int m = (l + r) / 2;
update(L, R, x, k, l, m, rt<<1);
update(L, R, x, k, m + 1, r, rt<<1|1);
pushup(rt);
}
long long query(int L, int R, int p, int l, int r, int rt)
{
if(L > r || R < L) return 0;
if(L <= l && R >= r){
return sum[rt][p];
}
pushdown(l, r, rt);
int m = (l + r) / 2;
return (query(L, R, p, l, m, rt<<1) + query(L, R, p, m + 1, r, rt<<1|1)) % mod;
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF && (n || m)){
build(1, n, 1);
int k, x, y, c;
for(int i = 0; i < m; i++){
scanf("%d%d%d%d", &k, &x, &y, &c);
if(k == 4){
printf("%lld\n", query(x, y, c, 1, n, 1));
}
else{
update(x, y, c, k, 1, n, 1);
}
}
}
return 0;
}