2018.08.18 数据结构题(线段树)

描述

给出一个长为n的序列

编号 输入格式 含义
1 1 l r 求区间 [ l , r ] 的和
2 2 l r 求区间 [ l , r ] 的最大值
3 3 l r 求区间 [ l , r ] 的最小值
4 4 l r x 将区间 [ l , r ] 内的所有数加上 x
5 5 i x 将第 i 个数按位异或 x
6 6 l r 求区间 [ l , r ] 内所有数的平均值(保留两位小数)
7 7 l r 将区间 [ l , r ] 内的所有数都变为原来的相反数
8 8 l r x 将区间 [ l , r ] 内的所有数赋值为 x
9 9 l r 求区间 [ l , r ] 内所有数的平方和

对于操作 1 和 9,输出要对 10 9 + 7 取模。

输入

第一行两个正整数 n,m 表示序列长度和操作个数。
之后的一行n 个整数,表示初始序列。
之后的 m 行,每行三个或四个正整数,表示一次操作。

输出

对于每一个操作 1、2、3、6、9,输出一行一个整数或小数,表示答案。

样例输入

5 4
1 2 3 4 5
4 1 2 3
2 4 5
8 2 3 4
9 3 4

样例输出

5
32
提示
N,M<=100000
对于100%的数据,区间和不会爆long long

这线段树真有(ma)趣(nong)啊。。。
调了半天发现把一个模号打成了乘号233,其实代码还是比较短的(也就3kb出头而已。。。)
如果考试考这题估计也只有打暴力的份了。。。

我的写法是pushdown时先传覆盖标记,再传取相反数标记,最后传区间加标记。

代码:

#include<bits/stdc++.h>
#define N 500005
#define ll long long
#define mod 1000000007
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
struct Node{int l,r,mx,mn;ll sum,sec,rev,cov,add;bool flag;}T[N<<2];
int n,m;
ll a[N];
inline ll read(){
    ll ans=0,w=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans*w;
}
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
inline void pushup(int p){
    T[p].sum=T[lc].sum+T[rc].sum,T[p].sec=(T[lc].sec+T[rc].sec)%mod;
    T[p].mx=max(T[lc].mx,T[rc].mx),T[p].mn=min(T[lc].mn,T[rc].mn);
}
inline void pushset(int p,ll v){
    T[p].flag=true,T[p].cov=T[p].mx=T[p].mn=v,T[p].add=T[p].rev=0;
    T[p].sum=(T[p].r-T[p].l+1)*v,T[p].sec=v*v%mod*(T[p].r-T[p].l+1)%mod;
}
inline void pushrev(int p){T[p].rev^=1,T[p].add=-T[p].add;T[p].sum=-T[p].sum,T[p].mx=-T[p].mx,T[p].mn=-T[p].mn,swap(T[p].mx,T[p].mn);}
inline void pushadd(int p,ll v){
    T[p].sec=(T[p].sec+v*v%mod*(T[p].r-T[p].l+1)%mod+T[p].sum%mod*2*v%mod+mod)%mod;
    T[p].sum+=v*(T[p].r-T[p].l+1),T[p].mx+=v,T[p].mn+=v,T[p].add+=v;
}
inline void pushdown(int p){
    if(T[p].flag)pushset(lc,T[p].cov),pushset(rc,T[p].cov),T[p].flag=false;
    if(T[p].rev)pushrev(lc),pushrev(rc),T[p].rev=0;
    if(T[p].add)pushadd(lc,T[p].add),pushadd(rc,T[p].add),T[p].add=0;
}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r,T[p].flag=false,T[p].rev=0,T[p].add=0;
    if(l==r){T[p].sum=T[p].mx=T[p].mn=a[l],T[p].sec=a[l]*a[l]%mod;return;}
    build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,ll v,int op){
    if(ql>T[p].r||qr<T[p].l)return;
    if(ql<=T[p].l&&T[p].r<=qr)return op==1?pushadd(p,v):(op==2?pushrev(p):pushset(p,v));
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v,op);
    else if(ql>mid)update(rc,ql,qr,v,op);
    else update(lc,ql,mid,v,op),update(rc,mid+1,qr,v,op);
    pushup(p);
}
inline ll solve(ll a,ll b,int op){return op<3?(op==1?a+b:(a+b)%mod):(op==3?max(a,b):min(a,b));}
inline ll query(int p,int ql,int qr,int op){
    if(ql>T[p].r||qr<T[p].l)return op<3?0:(op==3?-9223372036854775807:9223372036854775807);
    if(ql<=T[p].l&&T[p].r<=qr)return op<3?(op==1?T[p].sum:T[p].sec):(op==3?T[p].mx:T[p].mn);
    pushdown(p);
    if(qr<=mid)return query(lc,ql,qr,op);
    if(ql>mid)return query(rc,ql,qr,op);
    return solve(query(lc,ql,mid,op),query(rc,mid+1,qr,op),op);
}
inline void modify(int p,int k,ll x){
    if(T[p].l==T[p].r){T[p].sum^=x,T[p].mx^=x,T[p].mn^=x,T[p].sec=T[p].sum%mod*T[p].sum%mod;return;}
    pushdown(p);
    if(k<=mid)modify(lc,k,x);
    else modify(rc,k,x);
    pushup(p);
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;++i)a[i]=read();
    build(1,1,n);
    while(m--){
        int op=read();
        ll l=read(),r=read();
        if(op==1)printf("%lld\n",(query(1,l,r,1)%mod+mod)%mod);
        else if(op==2)printf("%lld\n",query(1,l,r,3));
        else if(op==3)printf("%lld\n",query(1,l,r,4));
        else if(op==4){ll x=read();update(1,l,r,x,1);}
        else if(op==5)modify(1,l,r);
        else if(op==6)printf("%.2lf\n",query(1,l,r,1)*1.0/(r-l+1));
        else if(op==7)update(1,l,r,0,2);
        else if(op==8){ll x=read();update(1,l,r,x,3);}
        else printf("%lld\n",query(1,l,r,2));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/81837594
今日推荐