HDU 4578 Transformation

2013杭州邀请赛的题目,当时我负责写这道题。然后被我写翔了。。。

现在组织好代码重写,幸运1A了。代码能力还是太弱。


题意:

三种操作,会询问[x,y]的一次方和,平方和,次方和


思路:

推推公式,开三个懒标记,累乘(mul),累乘累加(add),赋值(asi)。主要注意如何pushdown,还有要组织好代码。


sum[0]表示一次方的和,以此类推。

注意:更新必须从sum[2]~sum[0]


公式:

update:
p=1
+c:  sum[0] + n*c
*c:  sum[0]*c
=c:  n*c

p=2
+c:  sum[1] + n*c^2 + 2*c*sum[0]
*c:  sum[1]*c^2
=c:  n*c^2

p=3
+c:  sum[2] + n*c^3 + 3*c*sum[1] + 3*c^2 *sum[0]
*c:  sum[2]*c^3
=c:  n*c^3



pushdown:
p=1
mul*sum[0] + n*add

p=2
mul^2 * sum[1] + 2*mul*sum[0]*add + n*add^2

p=3
mul^3 * sum[2] + 3*mul^2 * sum[1]*add + 3*mul*sum[0]*add^2 + n*add^3


代码:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;

/*-------------------------Template----*/
#define N  100010
#define E  100010
#define ll long long
#define CB(x) ((x)*(x)*(x))
#define SQ(x)     ((x)*(x))
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
#define maxAry(a,n) max_element(a,a+(n))
#define minAry(a,n) min_element(a,a+(n))
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int PRIME =999983;
const int MOD   =10007;
const int MULTI =1000000007;
const double EPS=1e-9;
inline bool isodd(int x){return x&1;}
inline bool isodd(ll x) {return x&1;}
/*----------------------end Template----*/

class SegTree{
#define lson (rt<<1)
#define rson (rt<<1|1)
#define sgt seg[rt]
#define rtl seg[rt].l
#define rtr seg[rt].r
private:
    struct segment{
        int l,r,sum[3],asi,add,mul;
    }seg[N<<2];
public:
    void setMark(int op,int c,int rt)
    {
        if(op==1) sgt.add+=c;
        else if(op==2) sgt.mul*=c, sgt.add*=c;
        else sgt.asi=c, sgt.mul=1, sgt.add=0;
        sgt.mul%=MOD, sgt.add%=MOD;
    }
    void change(int op,ll c,int rt)
    {
        int n=rtr-rtl+1;
        switch(op){
            case 1: //+
                sgt.sum[2]+=(n*CB(c) + 3*c*sgt.sum[1] + 3*SQ(c)*sgt.sum[0])%MOD;
                sgt.sum[1]+=(n*SQ(c) + 2*c*sgt.sum[0])%MOD;
                sgt.sum[0]+=(n*c)%MOD;
            break;
            case 2: //*
                sgt.sum[2]*=CB(c)%MOD;
                sgt.sum[1]*=SQ(c)%MOD;
                sgt.sum[0]*=c;
            break;
            default://=
                sgt.sum[2]=n*CB(c)%MOD;
                sgt.sum[1]=n*SQ(c)%MOD;
                sgt.sum[0]=n*c%MOD;
        }
        sgt.sum[2]%=MOD;
        sgt.sum[1]%=MOD; 
        sgt.sum[0]%=MOD;
    }
    void refresh(ll mul,ll add,int rt)
    {
        int n=rtr-rtl+1;
        sgt.sum[2]=(CB(mul)*sgt.sum[2] + 3*SQ(mul)*sgt.sum[1]*add 
                    + 3*mul*sgt.sum[0]*SQ(add) + n*CB(add))%MOD;
        sgt.sum[1]=(SQ(mul)*sgt.sum[1] + 2*mul*sgt.sum[0]*add + n*SQ(add))%MOD;
        sgt.sum[0]=(mul*sgt.sum[0] + n*add)%MOD;
        sgt.sum[2]%=MOD;
        sgt.sum[1]%=MOD; 
        sgt.sum[0]%=MOD;
        sgt.mul=(sgt.mul*mul)%MOD;
        sgt.add=(sgt.add*mul+add)%MOD;        
    }
    void pushup(int rt)
    {
        for(int i=0;i<3;i++)
            sgt.sum[i]=(seg[lson].sum[i]+seg[rson].sum[i])%MOD;
    }
    void pushdown(int rt)
    {
        if(sgt.asi){
            change(3,sgt.asi,lson);
            change(3,sgt.asi,rson);
            setMark(3,sgt.asi,lson);
            setMark(3,sgt.asi,rson);
            sgt.asi=0;
        }
        if(sgt.mul!=1 || sgt.add){
           refresh(sgt.mul,sgt.add,lson);
           refresh(sgt.mul,sgt.add,rson);
           sgt.mul=1;
           sgt.add=0;
        }
    }
    void build(int l,int r,int rt)
    {
        rtl=l, rtr=r;
        CLR(sgt.sum,0);
        sgt.add=0;
        sgt.mul=1;
        sgt.asi=0;
        if(l==r) return ;
        int mid=(rtl+rtr)>>1;
        build(l,mid,lson);
        build(mid+1,r,rson);
    }
    void update(int op,int c,int L,int R,int rt)
    {
        if(L<=rtl && rtr<=R){
            change(op,c,rt);
            setMark(op,c,rt);
            return ;
        }
        int mid=(rtl+rtr)>>1;
        pushdown(rt);
        if(L<=mid) update(op,c,L,R,lson);
        if(mid<R) update(op,c,L,R,rson);
        pushup(rt);
    }
    int query(int op,int L,int R,int rt)
    {
        int ans=0;
        if(L<=rtl && rtr<=R)
            return sgt.sum[op-1];
        int mid=(rtl+rtr)>>1;
        pushdown(rt);
        if(L<=mid) ans+=query(op,L,R,lson);
        if(mid<R) ans+=query(op,L,R,rson);
        return ans%MOD;        
    }
}T;

int main()
{
    int n,m,l,r,c,op;
    while(scanf("%d%d",&n,&m),n||m){
        T.build(1,n,1);
        while(m--){
            scanf("%d%d%d%d",&op,&l,&r,&c);
            if(1<=op && op<=3){ 
                T.update(op,c,l,r,1);
            }else{
                printf("%d\n", T.query(c,l,r,1));
            }
        }
    }
    return 0;
}


你可能感兴趣的:(HDU 4578 Transformation)