HDU 4578 segment tree algorithm metaphysics?

Transformation

Topic Link

http://acm.hdu.edu.cn/showproblem.php?pid=4578

Problem Description

Yuanfang is puzzled with the question below:
There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<---ak+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<---ak×c, k = x,x+1,…,y.
Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay 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

The meaning of problems

Give you a sequence of four operations support

1. Interval addition

2. Interval multiplication

3. Interval Subtraction

4. Sum, sum of squares, i.e., cubic, and \ (\ large \ sum_ {i = l} ^ {r} {a_i ^ p} (1 \ le p \ le 3) \)

answer

This question is beginning to see, I think we can use mathematical formulas to make trouble, So now do come up with a formula, with sum1, sum2, sum3 and were kept, and square, cube and then re-engage time of the merger

Out. But I am feeling a lot of trouble, so the first Internet search of the investigation Correct answer is not what clever way. But after reading the online solution to a problem, I discovered the complexity of metaphysics are used.

So I happily followed suit everybody heavyweights as metaphysics operate it.

To do: with a tree line or encountered the same period of continuous intervals you can immediately get an answer, the rest of direct violence on the line, I wondered just put each number becomes different then cubed numbers and all direct on storm (do not think so, this question is purely entertainment).

Code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x7f7f7f7f
#define N 100050
#define mo 10007
ll n,m;
struct Node{ll l,r,lazy;};
struct segmentTree
{
    Node tr[N<<2];
    void push_up(ll x);
    void push_down(ll x);
    void bt(ll x,ll l,ll r);
    void add(ll x,ll l,ll r,ll tt);
    void multiply(ll x,ll l,ll r,ll tt);
    void cover(ll x,ll l,ll r,ll tt);
    ll query(ll x,ll l,ll r,ll tt);
}seg;
template<typename T>void read(T&x)
{
    ll k=0; char c=getchar();
    x=0;
    while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
    if (c==EOF)exit(0);
    while(isdigit(c))x=x*10+c-'0',c=getchar();
    x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void segmentTree::push_up(ll x)
{
    if(tr[x].l==tr[x].r)return;
    Node &a=tr[x<<1],&b=tr[x<<1|1];
    if (a.lazy==b.lazy&&tr[x].lazy==-1)tr[x].lazy=a.lazy;
}
void segmentTree::push_down(ll x)
{
    if (tr[x].lazy==-1)return;
    tr[x<<1].lazy=tr[x].lazy;
    tr[x<<1|1].lazy=tr[x].lazy;
    tr[x].lazy=-1;
}
void segmentTree::bt(ll x,ll l,ll r)
{
    tr[x]=Node{l,r,0};
    if (l==r)return;
    ll mid=(l+r)>>1;
    bt(x<<1,l,mid);
    bt(x<<1|1,mid+1,r);
}
void segmentTree::add(ll x,ll l,ll r,ll tt)
{
    if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
    {
        tr[x].lazy+=tt;
        tr[x].lazy%=mo;
        return;
    }
    ll mid=(tr[x].l+tr[x].r)>>1;
    push_down(x);
    if (l<=mid)add(x<<1,l,r,tt);
    if (mid<r)add(x<<1|1,l,r,tt);
    push_up(x);
}
void segmentTree::multiply(ll x,ll l,ll r,ll tt)
{
    if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
    {
        tr[x].lazy*=tt;
        tr[x].lazy%=mo;
        return;
    }
    ll mid=(tr[x].l+tr[x].r)>>1;
    push_down(x);
    if (l<=mid)multiply(x<<1,l,r,tt);
    if (mid<r)multiply(x<<1|1,l,r,tt);
    push_up(x);
}
void segmentTree::cover(ll x,ll l,ll r,ll tt)
{
    if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
    {
        tr[x].lazy=tt%mo;
        return;
    }
    ll mid=(tr[x].l+tr[x].r)>>1;
    push_down(x);
    if (l<=mid)cover(x<<1,l,r,tt);
    if (mid<r)cover(x<<1|1,l,r,tt);
    push_up(x);
}
ll segmentTree::query(ll x,ll l,ll r,ll tt)
{
    if (l<=tr[x].l&&tr[x].r<=r&&tr[x].lazy!=-1)
    {
        ll ans=1;
        for(ll i=1;i<=tt;i++)ans*=tr[x].lazy;
        ans*=(tr[x].r-tr[x].l+1);
        return ans%mo;
    }
    ll mid=(tr[x].l+tr[x].r)>>1,ans=0;
    push_down(x);
    if(l<=mid)ans+=query(x<<1,l,r,tt);
    if(mid<r)ans+=query(x<<1|1,l,r,tt);
    push_up(x);
    return ans%mo;
}
void work()
{
    read(n); read(m);
    if (n+m==0)exit(0);
    seg.bt(1,1,n);
    for(ll i=1;i<=m;i++)
    {
        ll id,x,y,tt;
        read(id); read(x); read(y); read(tt);
        if (id==1)seg.add(1,x,y,tt);
        if (id==2)seg.multiply(1,x,y,tt);
        if (id==3)seg.cover(1,x,y,tt);
        if (id==4)printf("%lld\n",seg.query(1,x,y,tt));
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("aa.in","r",stdin);
#endif
    while(1)work();
}

Guess you like

Origin www.cnblogs.com/mmmqqdd/p/11241062.html