CodeForces 266E More Queries to Array...

        因为k最大只有5,所以我建六个线段树,分别用于保存ai*i^k的值,这样就能在logn内算出值,所以此题总复杂度nlogn。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
struct Segment
{
    int l;
    int r;
    int mid;
    long long v;
    bool lazy;
    long long tag;
};
Segment tree[6][800000];
long long pi[6][100010];
long long si[6][100010];
long long a[100010];
long long MOD=1000000007;
int pow_mod(int a,int n)
{
    if (n == 0)
        return 1;
    if (n == 1)
        return a;
    int x=pow_mod(a,n/2);
    long long ans=((long long)x*x)%MOD;
    if (n%2 == 1)
        ans=(ans*a)%MOD;
    return (int)ans;
}
void init()
{
    long long i;
    memset(si,0,sizeof(si));
    memset(pi,0,sizeof(pi));
    for(i=0;i<=100000;i++)
    {
        int j;
        for(j=0;j<6;j++)
        {
            int k=j;
            long long tmp=1;
            while(k--)
            tmp=(tmp*i)%MOD;
            pi[j][i]=tmp;
            if(i!=0)
            si[j][i]=(si[j][i-1]+tmp)%MOD;
        }
    }
}
void pushdown(int w,int c)
{
    int t;
    int l,r;
    tree[w][c].lazy=false;
    l=tree[w][c<<1].l;
    r=tree[w][c<<1].r;
    tree[w][c<<1].v=((tree[w][c].tag*(si[w][r]-si[w][l-1]))%MOD+MOD)%MOD;
    tree[w][c<<1].lazy=true;
    tree[w][c<<1].tag=tree[w][c].tag;
    l=tree[w][c<<1|1].l;
    r=tree[w][c<<1|1].r;
    tree[w][c<<1|1].v=((tree[w][c].tag*(si[w][r]-si[w][l-1]))%MOD+MOD)%MOD;
    tree[w][c<<1|1].lazy=true;
    tree[w][c<<1|1].tag=tree[w][c].tag;
}
void build_tree(int w,int c,int l,int r)
{
    int mid;
    mid=(l+r)>>1;
    tree[w][c].l=l;
    tree[w][c].r=r;
    tree[w][c].mid=mid;
    tree[w][c].lazy=false;
    tree[w][c].tag=0;
    if (l == r)
    {
        tree[w][c].v=((a[l]*pi[w][l])%MOD+MOD)%MOD;
        return ;
    }
    build_tree(w,c<<1,l,mid);
    build_tree(w,c<<1|1,mid+1,r);
    tree[w][c].v=((tree[w][c<<1].v+tree[w][c<<1|1].v)%MOD+MOD)%MOD;
}
void update(int w,int c,int l,int r,int x)
{
    //printf("%d %d %d %d %d\n",w,c,l,r,x);
    if (tree[w][c].l == l && tree[w][c].r == r)
    {
        tree[w][c].lazy=true;
        tree[w][c].tag=x;
        tree[w][c].v=((tree[w][c].tag*(si[w][r]-si[w][l-1]))%MOD+MOD)%MOD;
        return ;
    }
    if (tree[w][c].lazy == true)
    {
        pushdown(w,c);
    }
    if (tree[w][c].mid >= r)
    {
        update(w,c<<1,l,r,x);
    }
    else if (tree[w][c].mid < l)
    {
        update(w,c<<1|1,l,r,x);
    }
    else
    {
        update(w,c<<1,l,tree[w][c].mid,x);
        update(w,c<<1|1,tree[w][c].mid+1,r,x);
    }
    tree[w][c].v=((tree[w][c<<1].v+tree[w][c<<1|1].v)%MOD+MOD)%MOD;
}
long long query(int w,int c,int l,int r)
{
    if (tree[w][c].l == l && tree[w][c].r == r)
    {
        return (long long)tree[w][c].v;
    }
    if (tree[w][c].lazy == true)
    {
        pushdown(w,c);
    }
    if (tree[w][c].mid >= r)
    {
        return query(w,c<<1,l,r);
    }
    else if (tree[w][c].mid < l)
    {
        return query(w,c<<1|1,l,r);
    }
    else
    {
        return ((query(w,c<<1,l,tree[w][c].mid)+query(w,c<<1|1,tree[w][c].mid+1,r))%MOD+MOD)%MOD;
    }
}
int getValue(int w,int l,int r,long long x,long long y)
{
    return ((query(w,1,l,r)*(((x*pi[y][l-1])%MOD+MOD)%MOD))%MOD+MOD)%MOD;
}
long long getSum(int k,int l,int r)
{
    long long ans;
    if (k == 0)
    {
        ans=((getValue(0,l,r,1,0))%MOD+MOD)%MOD;
    }
    else if (k == 1)
    {
        ans=((getValue(1,l,r,1,0)-getValue(0,l,r,1,1))%MOD+MOD)%MOD;
    }
    else if (k == 2)
    {
        ans=((((getValue(2,l,r,1,0)-getValue(1,l,r,2,1))%MOD+MOD)%MOD+getValue(0,l,r,1,2))%MOD+MOD)%MOD;
    }
    else if (k == 3)
    {
        ans=((((getValue(3,l,r,1,0)-getValue(2,l,r,3,1))%MOD+MOD)%MOD+((getValue(1,l,r,3,2)-getValue(0,l,r,1,3))%MOD+MOD)%MOD )%MOD+MOD)%MOD;
    }
    else if (k == 4)
    {
        ans=((((((getValue(4,l,r,1,0)-getValue(3,l,r,4,1))%MOD+MOD)%MOD+((getValue(2,l,r,6,2)-getValue(1,l,r,4,3))%MOD+MOD)%MOD)%MOD+MOD)%MOD+getValue(0,l,r,1,4))%MOD+MOD)%MOD;
    }
    else if (k == 5)
    {
        ans=((((((getValue(5,l,r,1,0)-getValue(4,l,r,5,1))%MOD+MOD)%MOD+((getValue(3,l,r,10,2)-getValue(2,l,r,10,3))%MOD+MOD)%MOD)%MOD+MOD)%MOD+((getValue(1,l,r,5,4)-getValue(0,l,r,1,5))%MOD+MOD)%MOD)%MOD+MOD)%MOD;
    }
    return ans;
}
int main()
{
    int n,m,t1,t2,t3,i;
    char o;
    init();
        scanf("%d%d",&n,&m);
    for (i=1; i<=n; i++)
    {
        scanf("%I64d",a+i);
    }
    for (i=0; i<6; i++)
        build_tree(i,1,1,n);
    while (m--)
    {
        scanf("%*c%c%d%d%d",&o,&t1,&t2,&t3);
        if (o == '?')
        {
            printf("%I64d\n",(getSum(t3,t1,t2)%MOD+MOD)%MOD);
        }
        else if (o == '=')
        {
            for (i=0; i<6; i++)
            {
                update(i,1,t1,t2,t3);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值