HDU 4578(线段树

题目:

要求支持四种区间操作:1.区间加上一个数,2.区间乘上一个数,3.区间全部变成一个数,4.区间求和(要求支持平方和,立方和.

思路:这题有些恶心啊.....幸而交上去1A,不然我感觉真得难以debug.....注意下传标记时三种操作的顺序.(常数有点大...估计是多余的mod造成的...

//priority_queue
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
#include <bitset>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) ((x)*(x))
#define eps (1e-8)
#define INF (0x3f3f3f3f)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

#define chl (o<<1)
#define chr ((o<<1)|1)
#define mi (l+((r-l)>>1))

const int mod=10007;
const int maxn=5e5;
inline int qpow(int a,int p){
    int ans=1;
    a%=mod;
    while(p>0){
        if(p&1) ans=ans*a%mod;
        a=a*a%mod;p>>=1;
    }
    return ans;
}
int val[3][maxn];
int add[maxn],mul[maxn],chg[maxn];
inline void ma(int &x,int b){x=(x+b)%mod;}
inline void mm(int &x,int b){x=x*b%mod;}
void _init(int o,int l,int r){
    val[0][o]=val[1][o]=val[2][o]=0;
    mul[o]=1,chg[o]=-1,add[o]=0;
    if(r-l<=1) return;
    _init(chl,l,mi);
    _init(chr,mi,r);
}
void change(int o,int l,int r,int x){
    val[0][o]=(r-l)*x%mod;
    val[1][o]=(r-l)*qpow(x,2)%mod;
    val[2][o]=(r-l)*qpow(x,3)%mod;
}
void changeAdd(int o,int l,int r,int x){
    ma(val[2][o],3*val[1][o]*x%mod+3*val[0][o]*x%mod*x%mod+sq(x)%mod*x%mod*
        (r-l)%mod);
    ma(val[1][o],val[0][o]*x*2%mod+sq(x)%mod*(r-l)%mod);
    ma(val[0][o],(r-l)*x);
}
void changeMul(int o,int l,int r,int x){
    mm(val[0][o],x);
    mm(val[1][o],qpow(x,2));
    mm(val[2][o],qpow(x,3));
}
void push(int o,int l,int r){
    if(r-l<=1) return;
    if(chg[o]!=-1){
        int x=chg[o];chg[o]=-1;
        add[chl]=add[chr]=0;
        mul[chl]=mul[chr]=1;
        chg[chl]=chg[chr]=x;
        change(chl,l,mi,x);
        change(chr,mi,r,x);
    }
    changeMul(chl,l,mi,mul[o]);changeAdd(chl,l,mi,add[o]);
    changeMul(chr,mi,r,mul[o]);changeAdd(chr,mi,r,add[o]);
    mm(mul[chl],mul[o]);mm(mul[chr],mul[o]);
    mm(add[chl],mul[o]);mm(add[chr],mul[o]);
    ma(add[chl],add[o]);ma(add[chr],add[o]);
    mul[o]=1,add[o]=0;
}
void update(int o,int l,int r){
    if(r-l<=1) return;
    val[0][o]=(val[0][chl]+val[0][chr])%mod;
    val[1][o]=(val[1][chl]+val[1][chr])%mod;
    val[2][o]=(val[2][chl]+val[2][chr])%mod;
}
void rangeMul(int o,int a,int b,int l,int r,int x){
    if(l>=b||r<=a) return;
    push(o,l,r);
    if(l>=a&&r<=b){
        changeMul(o,l,r,x);
        mm(mul[o],x);
        return;
    }
    rangeMul(chl,a,b,l,mi,x);
    rangeMul(chr,a,b,mi,r,x);
    update(o,l,r);
}
void rangeAdd(int o,int a,int b,int l,int r,int x){
    if(l>=b||r<=a) return;
    push(o,l,r);
    if(l>=a&&r<=b){
        changeAdd(o,l,r,x);
        ma(add[o],x);
        return;
    }
    rangeAdd(chl,a,b,l,mi,x);
    rangeAdd(chr,a,b,mi,r,x);
    update(o,l,r);
}
void rangeChange(int o,int a,int b,int l,int r,int x){
    if(l>=b||r<=a) return;
    push(o,l,r);
    if(l>=a&&r<=b){
        change(o,l,r,x);
        chg[o]=x;
        return;
    }
    rangeChange(chl,a,b,l,mi,x);
    rangeChange(chr,a,b,mi,r,x);
    update(o,l,r);
}
int query(int o,int a,int b,int l,int r,int x){
    if(l>=b||r<=a) return 0;
    push(o,l,r);
    if(l>=a&&r<=b) return val[x][o];
    return (query(chl,a,b,l,mi,x)+query(chr,a,b,mi,r,x))%mod;
}
int n,m;
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("/home/slyfc/CppFiles/out","w",stdout);
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0) break;
        _init(1,1,n+1);
        while(m--){
            int t,x,y,c;
            scanf("%d%d%d%d",&t,&x,&y,&c);
            if(t==1){
                rangeAdd(1,x,y+1,1,n+1,c);
            }else if(t==2){
                rangeMul(1,x,y+1,1,n+1,c);
            }else if(t==3){
                rangeChange(1,x,y+1,1,n+1,c);
            }else{
                printf("%d\n",query(1,x,y+1,1,n+1,c-1));
            }
        }
    }
    return 0;
}

时间: 2024-10-07 03:52:55

HDU 4578(线段树的相关文章

HDU 4578 线段树区间更新(确定区间操作的优先级)

HDU 4578 线段树区间更新 操作有: 区间所有数add(c) 区间所有数mul(c) 区间所有数set(c) 查询有: 区间所有数的p次方和(p>= 1 && p <= 3) 关键是区间更新的三种操作的优先级的确定清楚set>mul>add 关键是:down和update中对区间的更新操作是一回事,可以写成函数方便编程 //#pragma warning (disable: 4786) //#pragma comment (linker, "/STA

HDU 4578 线段树玄学算法?

Transformation 题目链接 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

K - Transformation HDU - 4578 线段树经典题(好题)

题意:区间  加   变成定值 乘  区间查询:和 平方和 立方和 思路:超级超级超级麻烦的一道题  设3个Lazy 标记分别为  change 改变mul乘 add加  优先度change>mul>add因为改变了之后 前面的mul 和add都失效了 push_down的时候    如果有change 标记 可以很方便得求p[1] p[2] p[3] 如果mul存在  则也可以很方便求得子区间的各种值 同时由于mul 比add优先  要把add标记*=value  相当于本来每个加5  乘以

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

hdu 4893 线段树 --- 也是两个变 类似双标记

http://acm.hdu.edu.cn/showproblem.php?pid=4893 开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对 参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍 #include <cstdio> #include <cstring> #include <a

HDU 4902 线段树||暴力

给定一个序列,两种操作 1:把一段变成x. 2:把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 线段树解法:用lazy标记下即可,优化方法还是很巧妙的, Accepted 4902 515MS 3308K 1941 B C++ #include "stdio.h" #include "string.h" struct node { int l,r,x;// 在叶子节点代表值,树节点代表成端更新的lazy操作. }data[400010]

HDU 4302 线段树单点更新,维护区间最大最小值

http://acm.hdu.edu.cn/showproblem.php?pid=4302 Problem Description Holedox is a small animal which can be considered as one point. It lives in a straight pipe whose length is L. Holedox can only move along the pipe. Cakes may appear anywhere in the p

HDU 3397 线段树 双懒惰标记

这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了 自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了 跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全部置为0或者1,没有置位的时候为-1 还有个rev标记,代表翻转操作,0代表当前不翻,1代表当前翻 要注意一下优先级,发现有不同的弄法,我是这个弄得,有set操作的时候,set标记设值,并把当前节点的rev标记设为0,因为不管要不要rev,当前set操作肯定直接覆盖了 rev操作不改变set操作,在