【ACM-ICPC 2018 徐州赛区网络预赛】H题 Features Track ---- 树状数组

版权声明:本文为博主原创文章,转载请预先通知博主(〃'▽'〃)。 https://blog.csdn.net/m0_37624640/article/details/82632700

题目链接

做法:

  • 我们知道我们想要的答案的式子中,相邻两项的系数差1,所以我们构造出类似这样的情况
  • 如下图所示

   n*a1         (n-1)*a2     (n-2)*a3    (n-3)*a4    (n-4)*a5   (n-5)*a6     (n-6)*a7     (n-7)*a8

  • 比如n = 8
  • 想查询[2,4]
  • 答案ans = (4-2+1)*a2+(4-2)*a3+(4-2-1)*a4 = 3*a2+2*a3+a4
  • 而构造的是 sum = 7*a2+6*a3+5*a4     他们之间超差了4倍的(a2+a3+a4)
  • 这时候我们发现了,我们可以使用树状数组的区间查询查找a2+a3+a4。我们只需要在求出sum,就可以
  • 通过作差求得ans。
  • 那么,怎么求sum呢?
  • 我们发现我们本身构造的这个式子,也可以通过树状数组维护,因为是可维护的!
  • 所以我们需要开三个数组,原数组,差分数组,sum数组( (n-i+1)*ai )
  • 然后区间维护,区间修改来维护就可以啦~~

AC代码:

#include<bits/stdc++.h>
#define IO          ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x)       push_back(x)
#define sz(x)       (int)(x).size()
#define sc(x)       scanf("%d",&x)
#define pr(x)       printf("%d\n",x)
#define abs(x)      ((x)<0 ? -(x) : x)
#define all(x)      x.begin(),x.end()
#define mk(x,y)     make_pair(x,y)
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const double PI = 4*atan(1.0);
const int maxm = 1e8+5;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
ll c1[maxn];
ll c2[maxn];
ll sum[maxn];
ll n,m;
inline ll read()
{
    char x;
    bool flag = false;
    while(x = getchar(),x<'0' || x>'9') if(x == '-') flag = true;
    ll u = x-'0';
    while(x = getchar(),x>='0' && x<='9') u = (u<<3)+(u<<1)+x-'0';
    if(flag) u = -u;
    return u;
}
inline ll lowbit(ll x) {return x&(-x);}
void update(ll *tree,ll x,ll val)
{
    for(ll i=x;i<=n;i+=lowbit(i)) tree[i]+=val;
}
ll getSum(ll *tree,ll x)
{
    ll res = 0;
    for(ll i=x;i;i-=lowbit(i)) res+=tree[i];
    return res;
}
ll query(ll x)
{
    ll ans1 = x*getSum(c1,x);
    ll ans2 = getSum(c2,x);
    return ans1-ans2;
}
ll range_query(ll l,ll r)
{
    return query(r)-query(l-1);
}
int main()
{
    #ifdef LOCAL_FILE
    freopen("in.txt","r",stdin);
    #endif // LOCAL_FILE
    n = read();m = read();
    ll l = 0,r;
    for(ll i=1;i<=n;i++)
    {
        r = read();
        update(c1,i,r-l);
        update(c2,i,(i-1)*(r-l));
        update(sum,i,(n-i+1)*r);
        l = r;
    }
    while(m--)
    {
        int c;sc(c);
        if(c == 1){
            ll l,r;
            l = read(); r = read();
            ll k = r-l+1;
            ll k1 = n-l+1;
            ll ans = range_query(l,r);
            ll res = getSum(sum,r)-getSum(sum,l-1);
            printf("%lld\n",res-(k1-k)*ans);
        }
        else{
            ll pos,nw;
            pos = read();nw = read();
            ll change = nw-getSum(c1,pos);
            update(c1,pos,change);
            update(c1,pos+1,-change);
            update(c2,pos,(pos-1)*change);
            update(c2,pos+1,-change*(pos));
            update(sum,pos,(n-pos+1)*change);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37624640/article/details/82632700