HDU 4578 Transformation line tree + mathematical formula derivation

Posted by iceblossom on Thu, 20 Feb 2020 04:12:32 +0100

Title Link

Title Description

In this paper, we give a sequence of length N, the initial values are all 0. Three operations are supported, and the sum of interval powers is maintained at the same time.
The first operation: interval plus a number.
The second operation: multiply the interval by a number.
The third operation: the interval becomes a number.

Input Description

No more than 10 groups of data, each group of data gives an N, m < 100000. Next line m describes the operation and query. The three operations correspond to (1,x,y,c), (2,x,y,c), (3,x,y,c), and the query corresponding to (4,x,y,p) represents the sum of the p-power of the query from X to y. (1 < = x < = y < = n, 1 < = C < = 10000, 1 < = P < = 3) read until N=0,M=0.

Output Description

For each inquiry, output the answer after taking the model of 10007

Water problem analysis

First of all, it is very easy to see that this is the problem of a line tree. The sum of the power required by the problem conforms to the interval merging property of the line tree. Temporarily determine the line tree to be used for this problem.

Next, let's look at the sum of powers required to be maintained by the title, P < = 3. We can maintain these three values at the same time and then output them respectively. But the sum of powers is obviously different from the sum of powers, which can not be obtained directly. It should be obtained by adding the sum of left and right sons. The sum of the powers of the interval is represented by s1s 〝 1S1, S2S 〝 2s2 and s3s 〝 3s3.

Three operations are discussed in turn.

Only the currently modified interval is considered. For operation 1:
A good solution of s1s 〝 1S1 is s1s 〝 1S1 + interval length LLL * plus XXX.

S1′=S1+L∗XS_1'=S_1+L*XS1′​=S1​+L∗X

When finding S2, first look at the situation when there is only one number in the interval, and set the unknown number AAA to get

(A+X)2=A2+2∗A∗X+X2(A+X)^2=A^2+2*A*X+X^2(A+X)2=A2+2∗A∗X+X2

It's easy to get. What if there are two numbers in the interval? Make this number BBB easy to get

(A+X)2+(B+X)2=(A2+B2)+2∗X∗(A+B)+2∗X2(A+X)^2+(B+X)^2=(A^2+B^2)+2*X*(A+B)+2*X^2(A+X)2+(B+X)2=(A2+B2)+2∗X∗(A+B)+2∗X2

Substitute s1s 〝 1S1, S2S 〝 2s2 with S2 ′ s 〝 S2 ′ to obtain

S2′=S2+2∗X∗S1+L∗X2S_2'=S_2+2*X*S_1+L*X^2S2′​=S2​+2∗X∗S1​+L∗X2

It can be inferred to the case where the interval length is N

The same method can be used to find the cubic sum

S3′=S3+3∗X∗S2+3∗S1∗X2+L∗X3S_3'=S_3+3*X*S_2+3*S_1*X^2+L*X^3S3′​=S3​+3∗X∗S2​+3∗S1​∗X2+L∗X3

So far, we can get the processing method of operation one

{S1′=S1+L∗XS2′=S2+2∗X∗S1+L∗X2S3′=S3+3∗X∗S2+3∗S1∗X2+L∗X3 \left\{ \begin{array}{c} S_1'=S_1+L*X \\ S_2'=S_2+2*X*S_1+L*X^2 \\ S_3'=S_3+3*X*S_2+3*S_1*X^2+L*X^3 \end{array} \right. ⎩⎨⎧​S1′​=S1​+L∗XS2′​=S2​+2∗X∗S1​+L∗X2S3′​=S3​+3∗X∗S2​+3∗S1​∗X2+L∗X3​

Now let's discuss how to handle operation 2:

From (k * A)2=K2 * A2(K*A)^2=K^2*A^2(K * A)2=K2 * A2, (k * A)3=K3 * A3(K*A)^3=K^3*A^3(K * A)3=K3 * A3

{S1′=K∗S1S2′=K2∗S2S3′=K3∗S3 \left\{ \begin{array}{c} S_1'=K*S_1\\ S_2'=K^2*S_2\\ S_3'=K^3*S_3 \end{array} \right. ⎩⎨⎧​S1′​=K∗S1​S2′​=K2∗S2​S3′​=K3∗S3​​

Operation 3 is the simplest:
It's equal to the sum of squares, cubes and L of the same number.

{S1′=L∗XS2′=L∗X2S3′=L∗X3 \left\{ \begin{array}{c} S_1'=L*X\\ S_2'=L*X^2\\ S_3'=L*X^3\\ \end{array} \right. ⎩⎨⎧​S1′​=L∗XS2′​=L∗X2S3′​=L∗X3​

Because they are interval operations, we usually use the lazy flag to update the subinterval. We define three lazy flags, add,mult,to, to respectively represent three operations. The last problem is how to deal with it when there are three markers in an interval at the same time.

There is no doubt that this step is preferred when there is a third operation, because the first two operations before this operation have been cleared when there is such a step. Therefore, compared with the other two operations, the third operation is the earliest and priority. At the same time, update the lazy of left and right sons, and clear the first two operations, namely

 tree[d<<1].lazyto=tree[d<<1|1].lazyto=x;
 tree[d<<1].lazymult=tree[d<<1|1].lazymult=1;
 tree[d<<1].lazyadd=tree[d<<1|1].lazymult=0;
 tree[d].lazyto=0;

The order of the first two operations is uncertain.
Let's first look at these two situations
Do the first operation before the second
(S1+A)∗B=B∗S1+A∗B(S_1+A)*B=B*S_1+A*B(S1​+A)∗B=B∗S1​+A∗B
Perform the second operation before the first
(B∗S1)+A=B∗S1+A(B*S_1)+A=B*S_1+A(B∗S1​)+A=B∗S1​+A
It can be observed that in both cases, we can convert to the case of multiplication first and then addition, so the priority of multiplication is higher than that of addition. At the same time, multiplication should be carried out first when it exists, but the addition should be multiplied by multiplier when it is passed to the son.

 tree[d].lazyadd=((tree[d].lazyadd%MOD)*x)%MOD;
 tree[d].lazymult=((tree[d].lazymult%MOD)*x)%MOD;

To sum up, the priority is
Ⅲ>Ⅱ>ⅠⅢ>Ⅱ>ⅠⅢ>Ⅱ>Ⅰ
At this point, the rest of the topic is to write carefully. Are the basic operations of line tree.
Also pay attention to the module operation. At the same time, lazymult starts from 1.

Attach Code:

#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<set>
#include<stack>
#define ll long long 
#define MAXN 500010
#define MAXM 810
#define INF 0x3f3f3f3f
//9223372036854775807
using namespace std;

const int MOD=10007;
int n,q,p=0,tim=0,ans=0;
int fa[MAXN],h[MAXN],in[MAXN],out[MAXN];
int a[810][810];
struct Tree {
 int l,r;
 ll lazyadd,lazymult,lazyto;
 ll sum[4];
}tree[MAXN];

void build(int d,int l,int r) {
 tree[d].l=l;tree[d].r=r;
 tree[d].lazyadd=tree[d].lazyto=0;
 tree[d].lazymult=1;
 for(int i=1;i<=3;++i) tree[d].sum[i]=0;
 if(l==r)return;
 int mid=(tree[d].l+tree[d].r)>>1;
 build(d<<1,l,mid);
 build(d<<1|1,mid+1,r);
}

void op1(int d,ll x) {
 ll temp=x;
 ll len=(ll)(tree[d].r-tree[d].l+1)%MOD;
 ll a1,a2,a3;
 tree[d].sum[3]=((tree[d].sum[3]%MOD)+(((tree[d].sum[2]%MOD)*(temp%MOD)*3)%MOD)+((tree[d].sum[1]*((temp*temp)%MOD)*3)%MOD)+((len*((((temp*temp)%MOD)*temp)%MOD))%MOD))%MOD;
 tree[d].sum[2]=((tree[d].sum[2]%MOD)+((((tree[d].sum[1]*temp)%MOD)*2)%MOD)+((len*((temp*temp)%MOD))%MOD))%MOD;
 tree[d].sum[1]=((tree[d].sum[1]%MOD)+(len*temp)%MOD)%MOD;//Pay attention to the order, because the sum before the change is needed, so it is from 3 to 1 
 tree[d].lazyadd=((tree[d].lazyadd%MOD)+(x%MOD))%MOD;
}

void op2(int d,ll x) {
 tree[d].sum[1]=(tree[d].sum[1]%MOD*x)%MOD;
 tree[d].sum[2]=((tree[d].sum[2]%MOD)*((x*x)%MOD))%MOD;
 tree[d].sum[3]=((tree[d].sum[3]%MOD)*(((x*x)%MOD)*x)%MOD)%MOD;
 tree[d].lazyadd=((tree[d].lazyadd%MOD)*x)%MOD;
 tree[d].lazymult=((tree[d].lazymult%MOD)*x)%MOD;
}

void op3(int d,ll x) {
 ll len=(tree[d].r-tree[d].l+1)%MOD;
 tree[d].sum[1]=(len*x)%MOD;
 tree[d].sum[2]=(len*((x*x)%MOD))%MOD;
 tree[d].sum[3]=(len*(((x*x)%MOD*x)%MOD))%MOD;
 tree[d].lazyto=x;
 tree[d].lazymult=1;
 tree[d].lazyadd=0;
}

void pushup(int d) {
 for(int i=1;i<=3;++i) tree[d].sum[i]=(tree[d<<1].sum[i]+tree[d<<1|1].sum[i])%MOD;
}

void pushdown(int d) {
 if(tree[d].lazyto) {
  op3(d<<1,tree[d].lazyto);
  op3(d<<1|1,tree[d].lazyto);
  tree[d].lazyto=0;
 }
 if(tree[d].lazymult!=1) {
  op2(d<<1,tree[d].lazymult);
  op2(d<<1|1,tree[d].lazymult);
  tree[d].lazymult=1;
 }
 if(tree[d].lazyadd) {
  op1(d<<1,tree[d].lazyadd);
  op1(d<<1|1,tree[d].lazyadd);
  tree[d].lazyadd=0;
 }
}

void modify(int d,int l,int r,ll x,int op) {
 if(tree[d].l==l&&tree[d].r==r) {
  if(op==1) {
   op1(d,x);
  }
  if(op==2) {
   op2(d,x);
  }
  if(op==3) {
   op3(d,x); 
  }
  return;
 }
 if(tree[d].lazyadd||tree[d].lazymult!=1||tree[d].lazyto) {
  pushdown(d);
 }
 int mid=(tree[d].l+tree[d].r)>>1;
 if(r<=mid) {
  modify(d<<1,l,r,x,op);
 }
 else {
  if(l>mid) {
   modify(d<<1|1,l,r,x,op);
  }
  else {
   modify(d<<1,l,mid,x,op);
   modify(d<<1|1,mid+1,r,x,op);
  }
 }
 pushup(d);
}

ll query(int d,int l,int r,int x) {
 if(tree[d].l==l&&tree[d].r==r) {
  return tree[d].sum[x]%MOD;
 }
 if(tree[d].lazyadd||tree[d].lazymult!=1||tree[d].lazyto) pushdown(d);
 int mid=(tree[d].l+tree[d].r)>>1;
 if(r<=mid) {
  return query(d<<1,l,r,x)%MOD;
 }
 else {
  if(l>mid) {
   return query(d<<1|1,l,r,x)%MOD;
  }
  else {
   return (query(d<<1,l,mid,x)+query(d<<1|1,mid+1,r,x))%MOD;
  }
 }
}

int main() {
 while(scanf("%d%d",&n,&q)!=EOF) {
  if(n==0&&q==0)break;
  build(1,1,n);
  for(int i=1;i<=q;++i) {
   int op,l,r;
   ll x;
   scanf("%d%d%d%lld",&op,&l,&r,&x);
   if(op==4) {
    printf("%lld\n",query(1,l,r,x));
   }
   else {
    modify(1,l,r,x,op);
   }
  }
 }
}
12 original articles published, 15 praised, 3201 visitors
Private letter follow

Topics: REST